diff options
author | Jordan Hargrave <jordan@cvs.openbsd.org> | 2005-11-21 17:23:20 +0000 |
---|---|---|
committer | Jordan Hargrave <jordan@cvs.openbsd.org> | 2005-11-21 17:23:20 +0000 |
commit | 6716439710b044e2cec4df518884e986deb002e2 (patch) | |
tree | f4a3c4267c6ecb167e83c00f525af97fe59ccd92 /sys | |
parent | 24ae1eb837a8bb677dd453e04d69f366f2a990f3 (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.c | 563 | ||||
-rw-r--r-- | sys/arch/i386/i386/esmreg.h | 210 | ||||
-rw-r--r-- | sys/arch/i386/i386/esmvar.h | 24 |
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; +}; + |