summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJordan Hargrave <jordan@cvs.openbsd.org>2005-11-21 17:23:20 +0000
committerJordan Hargrave <jordan@cvs.openbsd.org>2005-11-21 17:23:20 +0000
commit6716439710b044e2cec4df518884e986deb002e2 (patch)
treef4a3c4267c6ecb167e83c00f525af97fe59ccd92 /sys
parent24ae1eb837a8bb677dd453e04d69f366f2a990f3 (diff)
Add support for ESM (Embedded Server Management) for Dell PowerEdge servers.
Lot's of work by dlg@ ok marco@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/i386/esm.c563
-rw-r--r--sys/arch/i386/i386/esmreg.h210
-rw-r--r--sys/arch/i386/i386/esmvar.h24
3 files changed, 797 insertions, 0 deletions
diff --git a/sys/arch/i386/i386/esm.c b/sys/arch/i386/i386/esm.c
new file mode 100644
index 00000000000..4b46260f3ad
--- /dev/null
+++ b/sys/arch/i386/i386/esm.c
@@ -0,0 +1,563 @@
+/* $OpenBSD: esm.c,v 1.1 2005/11/21 17:23:19 jordan Exp $ */
+
+/*
+ * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/timeout.h>
+#include <sys/queue.h>
+#include <sys/sensors.h>
+
+#include <machine/bus.h>
+
+#include <arch/i386/i386/esmreg.h>
+#include <arch/i386/i386/esmvar.h>
+
+#define ESM_DEBUG
+
+#ifdef ESM_DEBUG
+#define DPRINTF(x...) do { if (esmdebug) printf(x); } while (0)
+#define DPRINTFN(n,x...) do { if (esmdebug > (n)) printf(x); } while (0)
+int esmdebug = 2;
+#else
+#define DPRINTF(x...) /* x */
+#define DPRINTFN(n,x...) /* n: x */
+#endif
+
+int esm_match(struct device *, void *, void *);
+void esm_attach(struct device *, struct device *, void *);
+
+struct esm_sensor_type {
+ enum sensor_type type;
+ long arg;
+#define ESM_A_PWRSUP_1 0x10
+#define ESM_A_PWRSUP_2 0x20
+#define ESM_A_PWRSUP_3 0x40
+#define ESM_A_PWRSUP_4 0x80
+ const char *name;
+};
+
+struct esm_sensor {
+ u_int8_t es_dev;
+ u_int8_t es_id;
+
+ long es_arg;
+
+ struct sensor es_sensor;
+ TAILQ_ENTRY(esm_sensor) es_entry;
+};
+
+struct esm_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ TAILQ_HEAD(, esm_sensor) sc_sensors;
+ struct timeout sc_timeout;
+};
+
+struct cfattach esm_ca = {
+ sizeof(struct esm_softc), esm_match, esm_attach
+};
+
+struct cfdriver esm_cd = {
+ NULL, "esm", DV_DULL
+};
+
+#define DEVNAME(s) ((s)->sc_dev.dv_xname)
+
+#define EREAD(s, r) bus_space_read_1((s)->sc_iot, (s)->sc_ioh, (r))
+#define EWRITE(s, r, v) bus_space_write_1((s)->sc_iot, (s)->sc_ioh, (r), (v))
+
+#define ECTRLWR(s, v) EWRITE((s), ESM2_TC_REG, (v))
+#define EDATARD(s) EREAD((s), ESM2_TBUF_REG)
+#define EDATAWR(s, v) EWRITE((s), ESM2_TBUF_REG, (v))
+
+void esm_refresh(void *);
+
+int esm_get_devmap(struct esm_softc *, int, struct esm_devmap *);
+void esm_devmap(struct esm_softc *, struct esm_devmap *);
+void esm_make_sensors(struct esm_softc *, struct esm_devmap *,
+ struct esm_sensor_type *, int);
+
+int esm_bmc_ready(struct esm_softc *, int, u_int8_t, u_int8_t);
+int esm_bmc_wait(struct esm_softc *, int, u_int8_t, u_int8_t);
+int esm_cmd(struct esm_softc *, void *, size_t, void *, size_t);
+int esm_smb_cmd(struct esm_softc *, struct esm_smb_req *,
+ struct esm_smb_resp *);
+
+int64_t esm_val2temp(u_int16_t);
+
+int
+esm_match(struct device *parent, void *match, void *aux)
+{
+ struct esm_attach_args *eaa = aux;
+
+ if (strncmp(eaa->eaa_name, esm_cd.cd_name,
+ sizeof(esm_cd.cd_name)) == 0)
+ return (1);
+
+ return (0);
+}
+
+void
+esm_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct esm_softc *sc = (struct esm_softc *)self;
+ struct esm_attach_args *eaa = aux;
+ u_int8_t x;
+
+ struct esm_devmap devmap;
+ int i;
+
+ sc->sc_iot = eaa->eaa_iot;
+ TAILQ_INIT(&sc->sc_sensors);
+
+ if (bus_space_map(sc->sc_iot, ESM2_BASE_PORT, 8, 0, &sc->sc_ioh) != 0) {
+ printf(": unable to map memory\n");
+ return;
+ }
+
+ /* turn off interrupts here */
+ x = EREAD(sc, ESM2_TIM_REG);
+ x &= ~(ESM2_TIM_SCI_EN|ESM2_TIM_SMI_EN|ESM2_TIM_NMI2SMI);
+ x |= ESM2_TIM_POWER_UP_BITS;
+ EWRITE(sc, ESM2_TIM_REG, x);
+
+ /* clear event doorbells */
+ x = EREAD(sc, ESM2_TC_REG);
+ x &= ~ESM2_TC_HOSTBUSY;
+ x |= ESM2_TC_POWER_UP_BITS;
+ EWRITE(sc, ESM2_TC_REG, x);
+
+ /* see if card is alive */
+ if (esm_bmc_wait(sc, ESM2_TC_REG, ESM2_TC_ECBUSY, 0) != 0) {
+ printf("%s: card is not alive\n");
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, 8);
+ return;
+ }
+
+ printf(": Watchdog shizz goes here\n");
+
+ for (i = 0; i <= 0xff; i++) {
+ if (esm_get_devmap(sc, i, &devmap) != 0)
+ break; /* XXX not continue? */
+ esm_devmap(sc, &devmap);
+ }
+
+ if (!TAILQ_EMPTY(&sc->sc_sensors)) {
+ DPRINTF("%s: starting refresh\n", DEVNAME(sc));
+ timeout_set(&sc->sc_timeout, esm_refresh, sc);
+ timeout_add(&sc->sc_timeout, hz * 10);
+ }
+}
+
+void
+esm_refresh(void *arg)
+{
+ struct esm_softc *sc = arg;
+ struct esm_sensor *sensor;
+ struct esm_smb_req req;
+ struct esm_smb_resp resp;
+ struct esm_smb_resp_val *val = &resp.resp_val;
+
+ memset(&req, 0, sizeof(req));
+ req.h_cmd = ESM2_CMD_SMB_XMIT_RECV;
+ req.h_txlen = sizeof(req.req_val);
+ req.h_rxlen = sizeof(resp.resp_val);
+ req.req_val.v_cmd = ESM2_SMB_SENSOR_VALUE;
+
+ TAILQ_FOREACH(sensor, &sc->sc_sensors, es_entry) {
+ req.h_dev = sensor->es_dev;
+ req.req_val.v_sensor = sensor->es_id;
+
+ if (esm_smb_cmd(sc, &req, &resp) != 0) {
+ sensor->es_sensor.flags |= SENSOR_FINVALID;
+ continue;
+ }
+
+ switch (sensor->es_sensor.type) {
+ case SENSOR_TEMP:
+ sensor->es_sensor.value = esm_val2temp(val->v_reading);
+ break;
+ default:
+ sensor->es_sensor.value = val->v_reading;
+ break;
+ }
+ }
+
+ timeout_add(&sc->sc_timeout, hz * 10);
+}
+
+int
+esm_get_devmap(struct esm_softc *sc, int dev, struct esm_devmap *devmap)
+{
+ struct esm_devmap_req req;
+ struct esm_devmap_resp resp;
+#ifdef ESM_DEBUG
+ int i;
+#endif
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req.cmd = ESM2_CMD_DEVICEMAP;
+ req.action = ESM2_DEVICEMAP_READ;
+ req.index = dev;
+ req.ndev = 1;
+
+ if (esm_cmd(sc, &req, sizeof(req), &resp, sizeof(resp)) != 0)
+ return (1);
+
+ if (resp.status != 0)
+ return (1);
+
+ memcpy(devmap, &resp.devmap[0], sizeof(struct esm_devmap));
+
+#ifdef ESM_DEBUG
+ if (esmdebug > 5) {
+ printf("\n");
+ printf("Device Map(%d) returns:\n", dev);
+ printf(" status: %.2x\n", resp.status);
+ printf(" #devs : %.2x\n", resp.ndev);
+ printf(" index: %.2x\n", resp.devmap[0].index);
+ printf(" Type : %.2x.%.2x\n", resp.devmap[0].dev_major,
+ resp.devmap[0].dev_minor);
+ printf(" Rev : %.2x.%.2x\n", resp.devmap[0].rev_major,
+ resp.devmap[0].rev_minor);
+ printf(" ROM : %.2x\n", resp.devmap[0].rev_rom);
+ printf(" SMB : %.2x\n", resp.devmap[0].smb_addr);
+ printf(" Stat : %.2x\n", resp.devmap[0].status);
+ printf(" MonTy: %.2x\n", resp.devmap[0].monitor_type);
+ printf(" Poll : %.2x\n", resp.devmap[0].pollcycle);
+ printf(" UUID : ");
+ for (i = 0; i < ESM2_UUID_LEN; i++) {
+ printf("%02x", resp.devmap[0].uniqueid[i]);
+ }
+ printf("\n");
+ }
+#endif /* ESM_DEBUG */
+
+ return (0);
+}
+
+struct esm_sensor_type esm_sensors_esm2[] = {
+ { SENSOR_INTEGER, 0, "Motherboard" },
+ { SENSOR_TEMP, 0, "CPU 1" },
+ { SENSOR_TEMP, 0, "CPU 2" },
+ { SENSOR_TEMP, 0, "CPU 3" },
+ { SENSOR_TEMP, 0, "CPU 4" },
+
+ { SENSOR_TEMP, 0, "Mainboard" },
+ { SENSOR_TEMP, 0, "Ambient" },
+ { SENSOR_VOLTS_DC, 0, "CPU 1 Core" },
+ { SENSOR_VOLTS_DC, 0, "CPU 2 Core" },
+ { SENSOR_VOLTS_DC, 0, "CPU 3 Core" },
+
+ { SENSOR_VOLTS_DC, 0, "CPU 4 Core" },
+ { SENSOR_VOLTS_DC, 0, "Motherboard +5V" },
+ { SENSOR_VOLTS_DC, 0, "Motherboard +12V" },
+ { SENSOR_VOLTS_DC, 0, "Motherboard +3.3V" },
+ { SENSOR_VOLTS_DC, 0, "Motherboard +2.5V" },
+
+ { SENSOR_VOLTS_DC, 0, "Motherboard GTL Term" },
+ { SENSOR_VOLTS_DC, 0, "Motherboard Battery" },
+ { SENSOR_INDICATOR, 0, "Chassis Intrusion", },
+ { SENSOR_INTEGER, 0, "Chassis Fan Ctrl", },
+ { SENSOR_FANRPM, 0, "Fan 1" },
+
+ { SENSOR_FANRPM, 0, "Fan 2" }, /* 20 */
+ { SENSOR_FANRPM, 0, "Fan 3" },
+ { SENSOR_FANRPM, 0, "Power Supply Fan" },
+ { SENSOR_VOLTS_DC, 0, "CPU 1 cache" },
+ { SENSOR_VOLTS_DC, 0, "CPU 2 cache" },
+
+ { SENSOR_VOLTS_DC, 0, "CPU 3 cache" },
+ { SENSOR_VOLTS_DC, 0, "CPU 4 cache" },
+ { SENSOR_INTEGER, 0, "Power Ctrl" },
+ { SENSOR_INTEGER, ESM_A_PWRSUP_1, "Power Supply 1" },
+ { SENSOR_INTEGER, ESM_A_PWRSUP_2, "Power Supply 2" },
+
+ { SENSOR_VOLTS_DC, 0, "Mainboard +1.5V" }, /* 30 */
+ { SENSOR_VOLTS_DC, 0, "Motherboard +2.8V" },
+ { SENSOR_INTEGER, 0, "HotPlug Status" },
+ { SENSOR_INTEGER, 1, "PCI Slot 1" },
+ { SENSOR_INTEGER, 2, "PCI Slot 2" },
+
+ { SENSOR_INTEGER, 3, "PCI Slot 3" },
+ { SENSOR_INTEGER, 4, "PCI Slot 4" },
+ { SENSOR_INTEGER, 5, "PCI Slot 5" },
+ { SENSOR_INTEGER, 6, "PCI Slot 6" },
+ { SENSOR_INTEGER, 7, "PCI Slot 7" },
+
+ { SENSOR_VOLTS_DC, 0, "CPU 1 Cartridge" }, /* 40 */
+ { SENSOR_VOLTS_DC, 0, "CPU 2 Cartridge" },
+ { SENSOR_VOLTS_DC, 0, "CPU 3 Cartridge" },
+ { SENSOR_VOLTS_DC, 0, "CPU 4 Cartridge" },
+ { SENSOR_VOLTS_DC, 0, "Gigabit NIC +1.8V" },
+
+ { SENSOR_VOLTS_DC, 0, "Gigabit NIC +2.5V" },
+ { SENSOR_VOLTS_DC, 0, "Memory +3.3V" },
+ { SENSOR_VOLTS_DC, 0, "Video +2.5V" },
+ { SENSOR_INTEGER, ESM_A_PWRSUP_3, "Power Supply 3" },
+ { SENSOR_FANRPM, 0, "Fan 4" },
+
+ { SENSOR_FANRPM, 0, "Power Supply Fan" }, /* 50 */
+ { SENSOR_FANRPM, 0, "Power Supply Fan" },
+ { SENSOR_FANRPM, 0, "Power Supply Fan" },
+ { SENSOR_INTEGER, 0, "A/C Power Switch" },
+ { SENSOR_INTEGER, 0, "PS Over Temp" }
+};
+
+void
+esm_devmap(struct esm_softc *sc, struct esm_devmap *devmap)
+{
+ struct esm_sensor_type *sensor_types;
+ const char *maj_name, *min_name;
+ int nsensors;
+
+ switch (devmap->dev_major) {
+ case ESM2_DEV_ESM2:
+ maj_name = "Embedded Server Management";
+ sensor_types = esm_sensors_esm2;
+
+ switch (devmap->dev_minor) {
+ case ESM2_DEV_ESM2_2300:
+ min_name = "PowerEdge 2300";
+ nsensors = 23;
+ break;
+ case ESM2_DEV_ESM2_4300:
+ min_name = "PowerEdge 4300";
+ nsensors = 27;
+ break;
+ case ESM2_DEV_ESM2_6300:
+ min_name = "PowerEdge 6300";
+ nsensors = 27;
+ break;
+ case ESM2_DEV_ESM2_6400:
+ min_name = "PowerEdge 6400";
+ nsensors = 44;
+ break;
+ case ESM2_DEV_ESM2_2550:
+ min_name = "PowerEdge 2550";
+ nsensors = 48;
+ break;
+ case ESM2_DEV_ESM2_4350:
+ min_name = "PowerEdge 4350";
+ nsensors = 27;
+ break;
+ case ESM2_DEV_ESM2_6350:
+ min_name = "PowerEdge 6350";
+ nsensors = 27;
+ break;
+ case ESM2_DEV_ESM2_6450:
+ min_name = "PowerEdge 6450";
+ nsensors = 44;
+ break;
+ case ESM2_DEV_ESM2_2400:
+ min_name = "PowerEdge 2400";
+ nsensors = 30;
+ break;
+ case ESM2_DEV_ESM2_4400:
+ min_name = "PowerEdge 4400";
+ nsensors = 44;
+ break;
+ case ESM2_DEV_ESM2_2500:
+ min_name = "PowerEdge 2500";
+ nsensors = 55;
+ break;
+ case ESM2_DEV_ESM2_2450:
+ min_name = "PowerEdge 2450";
+ nsensors = 27;
+ break;
+ case ESM2_DEV_ESM2_2400EX:
+ min_name = "PowerEdge 2400";
+ nsensors = 27;
+ break;
+ case ESM2_DEV_ESM2_2450EX:
+ min_name = "PowerEdge 2450";
+ nsensors = 44;
+ break;
+
+ default:
+ return;
+ }
+
+ printf("%s: %s %s %d.%d\n", DEVNAME(sc), min_name, maj_name,
+ devmap->rev_major, devmap->rev_minor);
+ break;
+
+ default:
+ return;
+ }
+
+ esm_make_sensors(sc, devmap, sensor_types, nsensors);
+}
+
+void
+esm_make_sensors(struct esm_softc *sc, struct esm_devmap *devmap,
+ struct esm_sensor_type *sensor_types, int nsensors)
+{
+ struct esm_smb_req req;
+ struct esm_smb_resp resp;
+ struct esm_smb_resp_val *val = &resp.resp_val;
+ struct esm_sensor *sensor;
+ int i;
+
+ memset(&req, 0, sizeof(req));
+ req.h_cmd = ESM2_CMD_SMB_XMIT_RECV;
+ req.h_dev = devmap->index;
+ req.h_txlen = sizeof(req.req_val);
+ req.h_rxlen = sizeof(resp.resp_val);
+
+ req.req_val.v_cmd = ESM2_SMB_SENSOR_VALUE;
+
+ for (i = 0; i < nsensors; i++) {
+ req.req_val.v_sensor = i;
+ if (esm_smb_cmd(sc, &req, &resp) != 0)
+ continue;
+
+ DPRINTFN(1, "%s: dev: 0x%02x sensor: %d (%s) "
+ "reading: 0x%04x status: 0x%02x cksum: 0x%02x\n",
+ DEVNAME(sc), devmap->index, i, sensor_types[i].name,
+ val->v_reading, val->v_status, val->v_checksum);
+
+ if ((val->v_status & ESM2_VS_VALID) != ESM2_VS_VALID)
+ continue;
+
+ sensor = malloc(sizeof(struct esm_sensor), M_DEVBUF, M_NOWAIT);
+ if (sensor == NULL)
+ goto error;
+
+ memset(sensor, 0, sizeof(struct esm_sensor));
+ sensor->es_dev = devmap->index;
+ sensor->es_id = i;
+ sensor->es_arg = sensor_types[i].arg;
+ sensor->es_sensor.type = sensor_types[i].type;
+ strlcpy(sensor->es_sensor.device, DEVNAME(sc),
+ sizeof(sensor->es_sensor.device));
+ strlcpy(sensor->es_sensor.desc, sensor_types[i].name,
+ sizeof(sensor->es_sensor.desc));
+ TAILQ_INSERT_TAIL(&sc->sc_sensors, sensor, es_entry);
+ SENSOR_ADD(&sensor->es_sensor);
+ }
+
+ return;
+
+error:
+ while (!TAILQ_EMPTY(&sc->sc_sensors)) {
+ sensor = TAILQ_FIRST(&sc->sc_sensors);
+ TAILQ_REMOVE(&sc->sc_sensors, sensor, es_entry);
+ free(sensor, M_DEVBUF);
+ }
+}
+
+
+int
+esm_bmc_ready(struct esm_softc *sc, int port, u_int8_t mask, u_int8_t val)
+{
+ if ((EREAD(sc, port) & mask) == val)
+ return (1);
+
+ return (0);
+}
+
+int
+esm_bmc_wait(struct esm_softc *sc, int port, u_int8_t mask, u_int8_t val)
+{
+ unsigned int count;
+
+ for (count = 0; count < 0xffffL; count++) {
+ if (esm_bmc_ready(sc, port, mask, val))
+ return (0);
+ }
+
+ return (1);
+}
+
+int
+esm_cmd(struct esm_softc *sc, void *cmd, size_t cmdlen, void *resp,
+ size_t resplen)
+{
+ u_int8_t *tx = (u_int8_t *)cmd;
+ u_int8_t *rx = (u_int8_t *)resp;
+ int i;
+
+ /* Wait for card ready */
+ if (esm_bmc_wait(sc, ESM2_TC_REG, ESM2_TC_READY, 0) != 0)
+ return (1); /* busy */
+
+ /* Write command data to port */
+ ECTRLWR(sc, ESM2_TC_CLR_WPTR);
+ for (i = 0; i < cmdlen; i++) {
+ DPRINTFN(2, "write: %.2x\n", *tx);
+ EDATAWR(sc, *tx);
+ tx++;
+ }
+
+ /* Ring doorbell and wait */
+ ECTRLWR(sc, ESM2_TC_H2ECDB);
+ if (esm_bmc_wait(sc, ESM2_TC_REG, ESM2_TC_EC2HDB, ESM2_TC_EC2HDB) != 0)
+ printf("post\n");
+
+ /* Set host busy semaphore and clear doorbell */
+ ECTRLWR(sc, ESM2_TC_HOSTBUSY);
+ ECTRLWR(sc, ESM2_TC_EC2HDB);
+
+ /* Read response data from port */
+ ECTRLWR(sc, ESM2_TC_CLR_RPTR);
+ for (i = 0; i < resplen; i++) {
+ *rx = EDATARD(sc);
+ DPRINTFN(2, "read = %.2x\n", *rx);
+ rx++;
+ }
+
+ /* release semaphore */
+ ECTRLWR(sc, ESM2_TC_HOSTBUSY);
+
+ return (0);
+}
+
+int
+esm_smb_cmd(struct esm_softc *sc, struct esm_smb_req *req,
+ struct esm_smb_resp *resp)
+{
+ memset(resp, 0, sizeof(struct esm_smb_resp));
+
+ if (esm_cmd(sc, req, sizeof(req->hdr) + req->h_txlen, resp,
+ sizeof(resp->hdr) + req->h_rxlen) != 0)
+ return (1);
+
+ if (resp->h_status != 0 || resp->h_i2csts != 0) {
+ DPRINTFN(3, "%s: dev: 0x%02x error status: 0x%02x "
+ "i2csts: 0x%02x procsts: 0x%02x tx: 0x%02x rx: 0x%02x\n",
+ __func__, req->h_dev, resp->h_status, resp->h_i2csts,
+ resp->h_procsts, resp->h_rx, resp->h_tx);
+ return (1);
+ }
+
+ return (0);
+}
+
+int64_t
+esm_val2temp(u_int16_t value)
+{
+ return (((int64_t)value/10 * 1000000) + 273150000);
+}
diff --git a/sys/arch/i386/i386/esmreg.h b/sys/arch/i386/i386/esmreg.h
new file mode 100644
index 00000000000..5017d8a5c69
--- /dev/null
+++ b/sys/arch/i386/i386/esmreg.h
@@ -0,0 +1,210 @@
+/* $OpenBSD: esmreg.h,v 1.1 2005/11/21 17:23:19 jordan Exp $ */
+
+/*
+ * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define ESM2_BASE_PORT 0xe0
+
+#if 0
+#define ESM2_TC_REG (ESM2_BASE_PORT + 4)
+#define ESM2_TBUF_REG (ESM2_BASE_PORT + 5)
+#define ESM2_TIM_REG (ESM2_BASE_PORT + 6)
+#else
+#define ESM2_TC_REG 4
+#define ESM2_TBUF_REG 5
+#define ESM2_TIM_REG 6
+#endif
+
+#define ESM2_TC_CLR_WPTR (1L << 0)
+#define ESM2_TC_CLR_RPTR (1L << 1)
+#define ESM2_TC_H2ECDB (1L << 2)
+#define ESM2_TC_EC2HDB (1L << 3)
+#define ESM2_TC_EVENTDB (1L << 4)
+#define ESM2_TC_HBDB (1L << 5)
+#define ESM2_TC_HOSTBUSY (1L << 6)
+#define ESM2_TC_ECBUSY (1L << 7)
+#define ESM2_TC_READY (ESM2_TC_EC2HDB | ESM2_TC_H2ECDB | \
+ ESM2_TC_ECBUSY)
+#define ESM2_TC_POWER_UP_BITS (ESM2_TC_CLR_WPTR | ESM2_TC_CLR_RPTR | \
+ ESM2_TC_EC2HDB | ESM2_TC_EVENTDB)
+
+#define ESM2_TIM_HIRQ_PEND (1L << 1)
+#define ESM2_TIM_SCI_EN (1L << 2)
+#define ESM2_TIM_SMI_EN (1L << 3)
+#define ESM2_TIM_NMI2SMI (1L << 4)
+#define ESM2_TIM_POWER_UP_BITS (ESM2_TIM_HIRQ_PEND)
+
+#define ESM2_CMD_NOOP 0x00
+#define ESM2_CMD_ECHO 0x01
+#define ESM2_CMD_DEVICEMAP 0x03
+#define ESM2_DEVICEMAP_READ 0
+
+#define ESM2_CMD_SMB_BUF 0x20
+#define ESM2_CMD_SMB_BUF_XMIT_RECV 0x21
+#define ESM2_CMD_SMB_XMIT_RECV 0x22
+#define ESM2_SMB_SENSOR_VALUE 0x04
+#define ESM2_SMB_SENSOR_THRESHOLDS 0x19
+
+#define ESM2_CMD_HWDC 0x05 /* Host Watch Dog Control */
+#define ESM2_HWDC_WRITE_STATE 0x01
+#define ESM2_HWDC_READ_PROPERTY 0x02
+#define ESM2_HWDC_WRITE_PROPERTY 0x03
+
+#define ESM2_MAX_CMD_LEN 0x20
+#define ESM2_UUID_LEN 0x08
+
+struct esm_watchdog_prop {
+ u_int8_t cmd;
+ u_int8_t reserved;
+ u_int8_t subcmd;
+ u_int8_t action;
+ u_int32_t time;
+} __packed;
+
+struct esm_watchdog_state {
+ u_int8_t cmd;
+ u_int8_t reserved;
+ u_int8_t subcmd;
+ u_int8_t state;
+} __packed;
+
+struct esm_devmap {
+ u_int8_t index;
+ u_int8_t dev_major;
+ u_int8_t dev_minor;
+ u_int8_t rev_major;
+ u_int8_t rev_minor;
+ u_int8_t rev_rom;
+ u_int8_t smb_addr;
+ u_int8_t status;
+ u_int8_t monitor_type;
+ u_int8_t pollcycle;
+ u_int8_t uniqueid[ESM2_UUID_LEN];
+} __packed;
+
+struct esm_devmap_req {
+ u_int8_t cmd;
+ u_int8_t initiator;
+ u_int8_t action;
+ u_int8_t index;
+ u_int8_t ndev;
+} __packed;
+
+struct esm_devmap_resp {
+ u_int8_t status;
+ u_int8_t ndev;
+ struct esm_devmap devmap[1]; /* request one map at a time */
+} __packed;
+
+
+/* ESM SMB requests */
+
+struct esm_smb_req_hdr {
+} __packed;
+
+struct esm_smb_req_val {
+ u_int8_t v_cmd;
+ u_int8_t v_initiator;
+ u_int8_t v_sensor;
+} __packed;
+
+struct esm_smb_req {
+ struct {
+ u_int8_t _cmd;
+ u_int8_t _dev;
+ u_int8_t _txlen;
+ u_int8_t _rxlen;
+ } __packed hdr;
+#define h_cmd hdr._cmd
+#define h_dev hdr._dev
+#define h_txlen hdr._txlen
+#define h_rxlen hdr._rxlen
+
+ union {
+ struct esm_smb_req_val _val;
+ } __packed _;
+#define req_val _._val
+
+} __packed;
+
+/* ESM SMB responses */
+
+struct esm_smb_resp_val {
+ u_int16_t v_reading;
+ u_int8_t v_status;
+ u_int8_t v_checksum;
+} __packed;
+
+struct esm_smb_resp {
+ struct {
+ u_int8_t _status;
+ u_int8_t _i2csts;
+ u_int8_t _procsts;
+ u_int8_t _tx;
+ u_int8_t _rx;
+ } __packed hdr;
+#define h_status hdr._status
+#define h_i2csts hdr._i2csts
+#define h_procsts hdr._procsts
+#define h_tx hdr._tx
+#define h_rx hdr._rx
+
+ union {
+ struct esm_smb_resp_val _val;
+ } __packed _;
+#define resp_val _._val
+} __packed;
+
+#define ESM2_VS_VALID 0x07
+#define ESM2_VS_SLOT 0x04
+
+#define isValidSensor(state) (((state) & ESM_STATE_MASK) == ESM_VALID_SENSOR)
+#define isValidSlot(state) (((state) & ESM_VALID_SLOT) == ESM_VALID_SLOT)
+
+enum esm_dev_type {
+ ESM2_DEV_ESM2 = 1,
+ ESM2_DEV_DRACII,
+ ESM2_DEV_FRONT_PANEL,
+ ESM2_DEV_BACKPLANE2,
+ ESM2_DEV_POWERUNIT2,
+ ESM2_DEV_ENCL2_BACKPLANE,
+ ESM2_DEV_ENCL2_POWERUNIT,
+ ESM2_DEV_ENCL1_BACKPLANE,
+ ESM2_DEV_ENCL1_POWERUNIT,
+ ESM2_DEV_HPPCI,
+ ESM2_DEV_BACKPLANE3
+};
+
+enum esm_dev_esm2_type {
+ ESM2_DEV_ESM2_2300 = 0,
+ ESM2_DEV_ESM2_4300,
+ ESM2_DEV_ESM2_6300,
+ ESM2_DEV_ESM2_6400,
+ ESM2_DEV_ESM2_2550,
+ ESM2_DEV_ESM2_4350,
+ ESM2_DEV_ESM2_6350,
+ ESM2_DEV_ESM2_6450,
+ ESM2_DEV_ESM2_2400,
+ ESM2_DEV_ESM2_4400,
+ ESM2_DEV_ESM2_R0, /* reserved */
+ ESM2_DEV_ESM2_2500,
+ ESM2_DEV_ESM2_2450,
+ ESM2_DEV_ESM2_R1, /* reserved */
+ ESM2_DEV_ESM2_R2, /* reserved */
+ ESM2_DEV_ESM2_2400EX,
+ ESM2_DEV_ESM2_2450EX
+};
+
diff --git a/sys/arch/i386/i386/esmvar.h b/sys/arch/i386/i386/esmvar.h
new file mode 100644
index 00000000000..09d5a899de6
--- /dev/null
+++ b/sys/arch/i386/i386/esmvar.h
@@ -0,0 +1,24 @@
+/* $OpenBSD: esmvar.h,v 1.1 2005/11/21 17:23:19 jordan Exp $ */
+
+/*
+ * Copyright (c) David Gwynne <dlg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct esm_attach_args {
+ char *eaa_name;
+ bus_space_tag_t eaa_iot;
+ bus_space_tag_t eaa_memt;
+};
+