diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-09-23 20:36:36 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-09-23 20:36:36 +0000 |
commit | 1ee07b66171b244428c25f0ad0e06d5e12a05efc (patch) | |
tree | cc54e9a166d4f3646ad7d65436b41f8cde78c70c /sys/arch/sparc64 | |
parent | 48b3286378df5a9d8307c4e0616a7c1a2e053067 (diff) |
Add some more LOMlite bits. We don't attach to LOMlite yet because it is
very slow and this version of the code busy waits too much.
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r-- | sys/arch/sparc64/dev/lom.c | 269 |
1 files changed, 217 insertions, 52 deletions
diff --git a/sys/arch/sparc64/dev/lom.c b/sys/arch/sparc64/dev/lom.c index bcc7249b8a0..1d309138172 100644 --- a/sys/arch/sparc64/dev/lom.c +++ b/sys/arch/sparc64/dev/lom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lom.c,v 1.9 2009/09/23 18:04:05 kettenis Exp $ */ +/* $OpenBSD: lom.c,v 1.10 2009/09/23 20:36:35 kettenis Exp $ */ /* * Copyright (c) 2009 Mark Kettenis * @@ -29,14 +29,22 @@ #include <sparc64/dev/ebusvar.h> /* - * The LOM is implemented as a H8/3437 microcontroller which has its + * LOMlite is a so far unidentified microcontroller. + */ +#define LOM1_STATUS 0x00 /* R */ +#define LOM1_STATUS_BUSY 0x80 +#define LOM1_CMD 0x00 /* W */ +#define LOM1_DATA 0x01 /* R/W */ + +/* + * LOMlite2 is implemented as a H8/3437 microcontroller which has its * on-chip host interface hooked up to EBus. */ -#define LOM_DATA 0x00 /* R/W */ -#define LOM_CMD 0x01 /* W */ -#define LOM_STATUS 0x01 /* R */ -#define LOM_STATUS_OBF 0x01 /* Output Buffer Full */ -#define LOM_STATUS_IBF 0x02 /* Input Buffer Full */ +#define LOM2_DATA 0x00 /* R/W */ +#define LOM2_CMD 0x01 /* W */ +#define LOM2_STATUS 0x01 /* R */ +#define LOM2_STATUS_OBF 0x01 /* Output Buffer Full */ +#define LOM2_STATUS_IBF 0x02 /* Input Buffer Full */ #define LOM_IDX_CMD 0x00 #define LOM_IDX_CMD_GENERIC 0x00 @@ -76,10 +84,23 @@ #define LOM_WDOG_AL3_WDOG 0x04 #define LOM_WDOG_AL3_FANPSU 0x08 #define LOM_IDX_WDOG_TIME 0x32 -#define LOM_WDOG_TIME_MAX 127 - -#define LOM_IDX_HOSTNAMELEN 0x38 -#define LOM_IDX_HOSTNAME 0x39 +#define LOM_WDOG_TIME_MAX 126 + +#define LOM1_IDX_HOSTNAME1 0x33 +#define LOM1_IDX_HOSTNAME2 0x34 +#define LOM1_IDX_HOSTNAME3 0x35 +#define LOM1_IDX_HOSTNAME4 0x36 +#define LOM1_IDX_HOSTNAME5 0x37 +#define LOM1_IDX_HOSTNAME6 0x38 +#define LOM1_IDX_HOSTNAME7 0x39 +#define LOM1_IDX_HOSTNAME8 0x3a +#define LOM1_IDX_HOSTNAME9 0x3b +#define LOM1_IDX_HOSTNAME10 0x3c +#define LOM1_IDX_HOSTNAME11 0x3d +#define LOM1_IDX_HOSTNAME12 0x3e + +#define LOM2_IDX_HOSTNAMELEN 0x38 +#define LOM2_IDX_HOSTNAME 0x39 #define LOM_IDX_CONFIG 0x5d #define LOM_IDX_FAN1_CAL 0x5e @@ -112,6 +133,9 @@ struct lom_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; + int sc_type; +#define LOM_LOMLITE 0 +#define LOM_LOMLITE2 2 int sc_space; struct ksensor sc_fan[LOM_MAX_FAN]; @@ -146,9 +170,15 @@ struct cfdriver lom_cd = { int lom_read(struct lom_softc *, uint8_t, uint8_t *); int lom_write(struct lom_softc *, uint8_t, uint8_t); +int lom1_read(struct lom_softc *, uint8_t, uint8_t *); +int lom1_write(struct lom_softc *, uint8_t, uint8_t); +int lom2_read(struct lom_softc *, uint8_t, uint8_t *); +int lom2_write(struct lom_softc *, uint8_t, uint8_t); int lom_init_desc(struct lom_softc *sc); void lom_refresh(void *); +void lom1_write_hostname(struct lom_softc *); +void lom2_write_hostname(struct lom_softc *); void lom_wdog_pat(void *); int lom_wdog_cb(void *, int); @@ -170,9 +200,12 @@ lom_attach(struct device *parent, struct device *self, void *aux) struct lom_softc *sc = (void *)self; struct ebus_attach_args *ea = aux; uint8_t reg, fw_rev, config, config2, config3; - uint8_t cal, low, len; + uint8_t cal, low; int i; + if (strcmp(ea->ea_name, "SUNW,lomh") == 0) + sc->sc_type = LOM_LOMLITE2; + if (ebus_bus_map(ea->ea_iotag, 0, EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { @@ -186,17 +219,27 @@ lom_attach(struct device *parent, struct device *self, void *aux) return; } + if (sc->sc_type < LOM_LOMLITE2) { + /* XXX Magic */ + bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca); + } + if (lom_read(sc, LOM_IDX_PROBE55, ®) || reg != 0x55 || lom_read(sc, LOM_IDX_PROBEAA, ®) || reg != 0xaa || lom_read(sc, LOM_IDX_FW_REV, &fw_rev) || - lom_read(sc, LOM_IDX_CONFIG, &config) || - lom_read(sc, LOM_IDX_CONFIG2, &config2) || - lom_read(sc, LOM_IDX_CONFIG3, &config3)) + lom_read(sc, LOM_IDX_CONFIG, &config)) { printf(": not responding\n"); return; } + config2 = config3 = 0; + if (sc->sc_type >= LOM_LOMLITE2) { + lom_read(sc, LOM_IDX_CONFIG2, &config2); + lom_read(sc, LOM_IDX_CONFIG3, &config3); + } + sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN); sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU); sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP); @@ -217,6 +260,8 @@ lom_attach(struct device *parent, struct device *self, void *aux) for (i = 0; i < sc->sc_num_fan; i++) { sc->sc_fan[i].type = SENSOR_FANRPM; sensor_attach(&sc->sc_sensordev, &sc->sc_fan[i]); + snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc), + "fan%d", i + 1); } for (i = 0; i < sc->sc_num_psu; i++) { sc->sc_psu[i].type = SENSOR_INDICATOR; @@ -240,13 +285,6 @@ lom_attach(struct device *parent, struct device *self, void *aux) sensordev_install(&sc->sc_sensordev); - /* Read hostname from LOM. */ - lom_read(sc, LOM_IDX_HOSTNAMELEN, &len); - for (i = 0; i < len; i++) { - lom_read(sc, LOM_IDX_HOSTNAME, ®); - sc->sc_hostname[i] = reg; - } - /* * We configure the watchdog to turn on the fault LED when the * watchdog timer expires. We run our own timeout to pat it @@ -271,46 +309,137 @@ lom_attach(struct device *parent, struct device *self, void *aux) int lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) { + if (sc->sc_type < LOM_LOMLITE2) + return lom1_read(sc, reg, val); + else + return lom2_read(sc, reg, val); +} + +int +lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val) +{ + if (sc->sc_type < LOM_LOMLITE2) + return lom1_write(sc, reg, val); + else + return lom2_write(sc, reg, val); +} + +int +lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) +{ uint8_t str; int i; + delay(15000); /* XXX */ + /* Wait for input buffer to become available. */ for (i = 1000; i > 0; i--) { - str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_STATUS); + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); delay(10); - if ((str & LOM_STATUS_IBF) == 0) + if ((str & LOM1_STATUS_BUSY) == 0) break; } if (i == 0) return (ETIMEDOUT); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM_CMD, reg); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg); + + delay(15000); /* XXX */ /* Wait until the microcontroller fills output buffer. */ for (i = 1000; i > 0; i--) { - str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_STATUS); + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); delay(10); - if (str & LOM_STATUS_OBF) + if ((str & LOM1_STATUS_BUSY) == 0) break; } if (i == 0) return (ETIMEDOUT); - *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_DATA); + *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); return (0); } int -lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val) +lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val) +{ + uint8_t str; + int i; + + delay(15000); /* XXX */ + + /* Wait for input buffer to become available. */ + for (i = 1000; i > 0; i--) { + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); + delay(10); + if ((str & LOM1_STATUS_BUSY) == 0) + break; + } + if (i == 0) + return (ETIMEDOUT); + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg | 0x80); + + delay(15000); /* XXX */ + + /* Wait until the microcontroller fills output buffer. */ + for (i = 1000; i > 0; i--) { + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); + delay(10); + if ((str & LOM1_STATUS_BUSY) == 0) + break; + } + if (i == 0) + return (ETIMEDOUT); + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val); + + return (0); +} + +int +lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) +{ + uint8_t str; + int i; + + /* Wait for input buffer to become available. */ + for (i = 1000; i > 0; i--) { + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); + delay(10); + if ((str & LOM2_STATUS_IBF) == 0) + break; + } + if (i == 0) + return (ETIMEDOUT); + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); + + /* Wait until the microcontroller fills output buffer. */ + for (i = 1000; i > 0; i--) { + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); + delay(10); + if (str & LOM2_STATUS_OBF) + break; + } + if (i == 0) + return (ETIMEDOUT); + + *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); + return (0); +} + +int +lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val) { uint8_t str; int i; /* Wait for input buffer to become available. */ for (i = 1000; i > 0; i--) { - str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_STATUS); + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); delay(10); - if ((str & LOM_STATUS_IBF) == 0) + if ((str & LOM2_STATUS_IBF) == 0) break; } if (i == 0) @@ -319,43 +448,43 @@ lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val) if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD) reg |= 0x80; - bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM_CMD, reg); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); /* Wait until the microcontroller fills output buffer. */ for (i = 1000; i > 0; i--) { - str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_STATUS); + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); delay(10); - if (str & LOM_STATUS_OBF) + if (str & LOM2_STATUS_OBF) break; } if (i == 0) return (ETIMEDOUT); - bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_DATA); + bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); /* Wait for input buffer to become available. */ for (i = 1000; i > 0; i--) { - str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_STATUS); + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); delay(10); - if ((str & LOM_STATUS_IBF) == 0) + if ((str & LOM2_STATUS_IBF) == 0) break; } if (i == 0) return (ETIMEDOUT); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM_DATA, val); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val); /* Wait until the microcontroller fills output buffer. */ for (i = 1000; i > 0; i--) { - str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_STATUS); + str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); delay(10); - if (str & LOM_STATUS_OBF) + if (str & LOM2_STATUS_OBF) break; } if (i == 0) return (ETIMEDOUT); - bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM_DATA); + bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); /* If we switched spaces, remember the one we're in now. */ if (reg == LOM_IDX_CMD) @@ -371,6 +500,10 @@ lom_init_desc(struct lom_softc *sc) int i, j, k; int error; + /* LOMlite doesn't provide sensor descriptions. */ + if (sc->sc_type < LOM_LOMLITE2) + return (0); + /* * Read temperature sensor names. */ @@ -389,6 +522,9 @@ lom_init_desc(struct lom_softc *sc) if (val == 0xff) break; + if (j < sizeof (sc->sc_temp[i].desc) - 1) + sc->sc_temp[i].desc[j++] = val; + if (val == '\0') { i++; j = 0; @@ -397,10 +533,6 @@ lom_init_desc(struct lom_softc *sc) break; } - - sc->sc_temp[i].desc[j++] = val; - if (j > sizeof (sc->sc_temp[i].desc) - 1) - break; } /* @@ -421,6 +553,9 @@ lom_init_desc(struct lom_softc *sc) if (val == 0xff) break; + if (j < sizeof (sc->sc_fan[i].desc) - 1) + sc->sc_fan[i].desc[j++] = val; + if (val == '\0') { i++; j = 0; @@ -429,10 +564,6 @@ lom_init_desc(struct lom_softc *sc) break; } - - sc->sc_fan[i].desc[j++] = val; - if (j > sizeof (sc->sc_fan[i].desc) - 1) - break; } fail: @@ -498,14 +629,48 @@ lom_refresh(void *arg) */ if (hostnamelen > 0 && strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) { - lom_write(sc, LOM_IDX_HOSTNAMELEN, hostnamelen + 1); - for (i = 0; i < hostnamelen + 1; i++) - lom_write(sc, LOM_IDX_HOSTNAME, hostname[i]); + if (sc->sc_type < LOM_LOMLITE2) + lom1_write_hostname(sc); + else + lom2_write_hostname(sc); strlcpy(sc->sc_hostname, hostname, sizeof(hostname)); } } void +lom1_write_hostname(struct lom_softc *sc) +{ + char name[LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1]; + char *p; + int i; + + /* + * LOMlite generally doesn't have enough space to store the + * fully qualified hostname. If the hostname is too long, + * strip off the domain name. + */ + strlcpy(name, hostname, sizeof(name)); + if (hostnamelen > sizeof(name)) { + p = strchr(name, '.'); + if (p) + *p = '\0'; + } + + for (i = 0; i < strlen(name) + 1; i++) + lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i]); +} + +void +lom2_write_hostname(struct lom_softc *sc) +{ + int i; + + lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1); + for (i = 0; i < hostnamelen + 1; i++) + lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]); +} + +void lom_wdog_pat(void *arg) { struct lom_softc *sc; |