summaryrefslogtreecommitdiff
path: root/sys/scsi
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2005-08-18 12:26:41 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2005-08-18 12:26:41 +0000
commit16c022ab453d5dde1be797f48f79758fa077cd5c (patch)
tree8d6f22442cb11b66b8cb2ede78cf72bb71f2c636 /sys/scsi
parent3aceaebc75df9090b2684887634a1046d7b62b7a (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.c174
-rw-r--r--sys/scsi/ses.h36
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 */