diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2005-08-18 12:26:41 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2005-08-18 12:26:41 +0000 |
commit | 16c022ab453d5dde1be797f48f79758fa077cd5c (patch) | |
tree | 8d6f22442cb11b66b8cb2ede78cf72bb71f2c636 /sys/scsi | |
parent | 3aceaebc75df9090b2684887634a1046d7b62b7a (diff) |
infrastructure to support blinking controlled via /dev/bio ioctls. the
code to do the actual blink is ifdefed out till marco can figure out what
im doing wrong.
Diffstat (limited to 'sys/scsi')
-rw-r--r-- | sys/scsi/ses.c | 174 | ||||
-rw-r--r-- | sys/scsi/ses.h | 36 |
2 files changed, 199 insertions, 11 deletions
diff --git a/sys/scsi/ses.c b/sys/scsi/ses.c index a8650be60d4..f59d571356d 100644 --- a/sys/scsi/ses.c +++ b/sys/scsi/ses.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ses.c,v 1.21 2005/08/13 01:38:19 dlg Exp $ */ +/* $OpenBSD: ses.c,v 1.22 2005/08/18 12:26:39 dlg Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "bio.h" + #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> @@ -28,6 +30,10 @@ #include <sys/kthread.h> #include <sys/sensors.h> +#if NBIO > 0 +#include <dev/biovar.h> +#endif + #include <scsi/scsi_all.h> #include <scsi/scsi_disk.h> #include <scsi/scsiconf.h> @@ -55,6 +61,14 @@ struct ses_sensor { TAILQ_ENTRY(ses_sensor) se_entry; }; +#if NBIO > 0 +struct ses_slot { + struct ses_status *sl_stat; + + TAILQ_ENTRY(ses_slot) sl_entry; +}; +#endif + struct ses_thread; struct ses_softc { @@ -69,6 +83,9 @@ struct ses_softc { u_char *sc_buf; ssize_t sc_buflen; +#if NBIO > 0 + TAILQ_HEAD(, ses_slot) sc_slots; +#endif TAILQ_HEAD(, ses_sensor) sc_sensors; struct ses_thread *sc_thread; }; @@ -98,6 +115,12 @@ int ses_read_status(struct ses_softc *, int); int ses_make_sensors(struct ses_softc *, struct ses_type_desc *, int); int ses_refresh_sensors(struct ses_softc *); +#if NBIO > 0 +int ses_ioctl(struct device *, u_long, caddr_t); +int ses_write_config(struct ses_softc *); +int ses_bio_blink(struct ses_softc *, struct bioc_blink *); +#endif + void ses_psu2sensor(struct ses_softc *, struct ses_sensor *); void ses_cool2sensor(struct ses_softc *, struct ses_sensor *); void ses_temp2sensor(struct ses_softc *, struct ses_sensor *); @@ -158,7 +181,19 @@ ses_attach(struct device *parent, struct device *self, void *aux) sc->sc_thread->sc = sc; sc->sc_thread->running = 1; +#if NBIO > 0 + if (bio_register(self, ses_ioctl) != 0) { + free(sc->sc_thread, M_DEVBUF); + sc->sc_thread = NULL; + printf("%s: unable to register ioctl\n", DEVNAME(sc)); + return; + } +#endif + if (ses_read_config(sc) != 0) { +#if NBIO > 0 + bio_unregister(self); +#endif free(sc->sc_thread, M_DEVBUF); sc->sc_thread = NULL; printf("%s: unable to read enclosure configuration\n", @@ -174,12 +209,25 @@ ses_detach(struct device *self, int flags) { struct ses_softc *sc = (struct ses_softc *)self; struct ses_sensor *sensor; +#if NBIO > 0 + struct ses_slot *slot; +#endif if (sc->sc_thread != NULL) { sc->sc_thread->running = 0; wakeup(sc->sc_thread); sc->sc_thread = NULL; +#if NBIO > 0 + bio_unregister(self); + + while (!TAILQ_EMPTY(&sc->sc_slots)) { + slot = TAILQ_FIRST(&sc->sc_slots); + TAILQ_REMOVE(&sc->sc_slots, slot, sl_entry); + free(slot, M_DEVBUF); + } +#endif + /* * We can't free the sensors once theyre in the systems sensor * list, so just mark them as invalid. @@ -212,15 +260,14 @@ ses_refresh(void *arg) while (thread->running) { if (ses_refresh_sensors(sc) != 0) { if (ok) - printf("%s: error reading enclosure status\n", - DEVNAME(sc)); + printf("%s: status read error\n", DEVNAME(sc)); ok = 0; } else { if (!ok) - printf("%s: reading enclosure status\n", - DEVNAME(sc)); + printf("%s: status read ok\n", DEVNAME(sc)); ok = 1; } + tsleep(thread, PWAIT, "timeout", 10 * hz); } @@ -362,6 +409,9 @@ ses_make_sensors(struct ses_softc *sc, struct ses_type_desc *types, int ntypes) { struct ses_status *status; struct ses_sensor *sensor; +#if NBIO > 0 + struct ses_slot *slot; +#endif enum sensor_type stype; char *fmt; int typecnt[SES_NUM_TYPES]; @@ -372,6 +422,9 @@ ses_make_sensors(struct ses_softc *sc, struct ses_type_desc *types, int ntypes) memset(typecnt, 0, sizeof(typecnt)); TAILQ_INIT(&sc->sc_sensors); +#if NBIO > 0 + TAILQ_INIT(&sc->sc_slots); +#endif status = (struct ses_status *)(sc->sc_buf + SES_STAT_HDRLEN); for (i = 0; i < ntypes; i++) { @@ -392,6 +445,22 @@ ses_make_sensors(struct ses_softc *sc, struct ses_type_desc *types, int ntypes) continue; switch (types[i].type) { +#if NBIO > 0 + case SES_T_DEVICE: + slot = malloc(sizeof(struct ses_slot), + M_DEVBUF, M_NOWAIT); + if (slot == NULL) + goto error; + + memset(slot, 0, sizeof(struct ses_slot)); + slot->sl_stat = status; + + TAILQ_INSERT_TAIL(&sc->sc_slots, slot, + sl_entry); + + continue; +#endif + case SES_T_POWERSUPPLY: stype = SENSOR_INDICATOR; fmt = "psu%d"; @@ -437,6 +506,13 @@ ses_make_sensors(struct ses_softc *sc, struct ses_type_desc *types, int ntypes) SENSOR_ADD(&sensor->se_sensor); return (0); error: +#if NBIO > 0 + while (!TAILQ_EMPTY(&sc->sc_slots)) { + slot = TAILQ_FIRST(&sc->sc_slots); + TAILQ_REMOVE(&sc->sc_slots, slot, sl_entry); + free(slot, M_DEVBUF); + } +#endif while (!TAILQ_EMPTY(&sc->sc_sensors)) { sensor = TAILQ_FIRST(&sc->sc_sensors); TAILQ_REMOVE(&sc->sc_sensors, sensor, se_entry); @@ -503,6 +579,94 @@ ses_refresh_sensors(struct ses_softc *sc) return (ret); } +#if NBIO > 0 +int +ses_ioctl(struct device *dev, u_long cmd, caddr_t addr) +{ + struct ses_softc *sc = (struct ses_softc *)dev; + int error = 0; + + switch (cmd) { + case BIOCBLINK: + error = ses_bio_blink(sc, (struct bioc_blink *)addr); + break; + + default: + error = EINVAL; + break; + } + + return (error); +} + +int +ses_write_config(struct ses_softc *sc) +{ + struct ses_scsi_diag cmd; + int flags; + + memset(&cmd, 0, sizeof(cmd)); + cmd.opcode = SEND_DIAGNOSTIC; + cmd.flags |= SES_DIAG_PCV; + cmd.length = htobe16(sc->sc_buflen); + flags = SCSI_DATA_OUT; +#ifndef SCSIDEBUG + flags |= SCSI_SILENT; +#endif + + if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd, + sizeof(cmd), sc->sc_buf, sc->sc_buflen, 2, 3000, NULL, flags) != 0) + return (1); + + return (0); +} + +int +ses_bio_blink(struct ses_softc *sc, struct bioc_blink *blink) +{ +#if notyet + struct ses_slot *slot; + + /* XXX isnt strictly needed? */ + if (ses_read_status(sc, 1) != 0) + return (EIO); + + TAILQ_FOREACH(slot, &sc->sc_slots, sl_entry) { + if (SES_S_DEV_ADDR(slot->sl_stat) == blink->bb_target) + break; + } + + if (slot == TAILQ_END(&sc->sc_slots)) + return (EINVAL); + + /* zero out the config fields */ + /* XXX previous config is lost */ + slot->sl_stat->f2 = 0x00; + slot->sl_stat->f3 = 0x00; + + switch (blink->bb_status) { + case BIOC_SBUNBLINK: + break; + + case BIOC_SBBLINK: + SES_C_DEV_IDENT(slot->sl_stat); + break; + + case BIOC_SBALARM: + SES_C_DEV_FAULT(slot->sl_stat); + break; + + default: + return (EINVAL); + } + + if (ses_write_config(sc) != 0) + return (EIO); +#endif /* notyet */ + return (0); +} +#endif + void ses_psu2sensor(struct ses_softc *sc, struct ses_sensor *s) { diff --git a/sys/scsi/ses.h b/sys/scsi/ses.h index 3b6cc5c9028..2d3f889634f 100644 --- a/sys/scsi/ses.h +++ b/sys/scsi/ses.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ses.h,v 1.5 2005/08/03 15:34:13 dlg Exp $ */ +/* $OpenBSD: ses.h,v 1.6 2005/08/18 12:26:40 dlg Exp $ */ /* * Copyright (c) 2005 Marco Peereboom * All rights reserved. @@ -31,7 +31,7 @@ /* the scsi command */ struct ses_scsi_diag { - u_int8_t opcode; /* RECEIVE_DIAGNOSTIC */ + u_int8_t opcode; /* SEND_DIAGNOSTIC or RECEIVE_DIAGNOSTIC */ u_int8_t flags; #define SES_DIAG_PCV (1<<0) /* page code valid */ u_int8_t pgcode; @@ -143,11 +143,35 @@ struct ses_status { } __packed; #define SES_STAT_ELEMLEN sizeof(struct ses_status) -/* device */ +/* device status */ #define SES_S_DEV_ADDR(d) ((d)->f1) -#define SES_S_DEV_RDYTOINS(d) ((d)->f2 & (1<<3)) /* ready to insert */ -#define SES_S_DEV_DONOTREM(d) ((d)->f2 & (1<<6)) /* no not remove */ -/* XXX FINISH THIS */ +#define SES_S_DEV_REPORT(d) ((d)->f2 & (1<<0)) /* enc report in progress */ +#define SES_S_DEV_IDENT(d) ((d)->f2 & (1<<1)) /* currently identifying */ +#define SES_S_DEV_REMOVE(d) ((d)->f2 & (1<<2)) /* ready to remove */ +#define SES_S_DEV_INSERT(d) ((d)->f2 & (1<<3)) /* ready to insert */ +#define SES_S_DEV_ENCBYPB(d) ((d)->f2 & (1<<4)) /* port B bypassed by enc */ +#define SES_S_DEV_ENCBYPA(d) ((d)->f2 & (1<<5)) /* port A bypassed by enc */ +#define SES_S_DEV_DONOTREM(d) ((d)->f2 & (1<<6)) /* do not remove */ +#define SES_S_DEV_APPCLBYPA(d) ((d)->f2 & (1<<7)) /* port A bypassed by app */ +#define SES_S_DEV_DEVBYPB(d) ((d)->f3 & (1<<0)) /* port B bypassed by dev */ +#define SES_S_DEV_DEVBYPA(d) ((d)->f3 & (1<<1)) /* port A bypassed by dev */ +#define SES_S_DEV_BYPB(d) ((d)->f3 & (1<<2)) +#define SES_S_DEV_BYPA(d) ((d)->f3 & (1<<3)) +#define SES_S_DEV_OFF(d) ((d)->f3 & (1<<4)) /* device is off */ +#define SES_S_DEV_FAULTRQST(d) ((d)->f3 & (1<<5)) /* fault indicator rqsted */ +#define SES_S_DEV_FAULTSENSE(d) ((d)->f3 & (1<<6)) /* fault sensed */ +#define SES_S_DEV_APPCLBYPB(d) ((d)->f3 & (1<<7)) /* port B bypassed by app */ + +/* device configuration */ +#define SES_C_DEV_IDENT(d) ((d)->f2 |= (1<<1)) /* ident */ +#define SES_C_DEV_REMOVE(d) ((d)->f2 |= (1<<2)) /* remove */ +#define SES_C_DEV_INSERT(d) ((d)->f2 |= (1<<3)) /* insert */ +#define SES_C_DEV_DONOTREM(d) ((d)->f2 |= (1<<6)) /* do not remove */ +#define SES_C_DEV_ACTIVE(d) ((d)->f2 |= (1<<7)) /* active indicator */ +#define SES_C_DEV_BYPB(d) ((d)->f3 |= (1<<2)) /* port B bypass */ +#define SES_C_DEV_BYPA(d) ((d)->f3 |= (1<<3)) /* port A bypass */ +#define SES_C_DEV_OFF(d) ((d)->f3 |= (1<<4)) /* off */ +#define SES_C_DEV_FAULT(d) ((d)->f3 |= (1<<5)) /* fault indicator */ /* power supply element */ #define SES_S_PSU_IDENT(d) ((d)->f1 & (1<<6)) /* identify */ |