summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2009-08-13 19:49:32 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2009-08-13 19:49:32 +0000
commitd06ea8d6af646f586c211f6a363f1977dfd32d09 (patch)
tree1e376f441cb2fdf6cd19f60d7e020319c69ee743
parent72ef9249fe7b9db3f67599f74ec74ca8ca1c8e1d (diff)
provide an api for an interrupt (or something like it) to notify the
midlayer that a scsi device has appeared or dissapeared. the midlayer will queue an event and run it in the system workq (which has process context) to handle the attach or detach.
-rw-r--r--sys/scsi/scsi_base.c85
-rw-r--r--sys/scsi/scsiconf.h5
2 files changed, 88 insertions, 2 deletions
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
index 0990920194a..ec43d205eec 100644
--- a/sys/scsi/scsi_base.c
+++ b/sys/scsi/scsi_base.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi_base.c,v 1.132 2009/06/02 06:33:04 yuo Exp $ */
+/* $OpenBSD: scsi_base.c,v 1.133 2009/08/13 19:49:31 dlg Exp $ */
/* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */
/*
@@ -66,6 +66,16 @@ char *scsi_decode_sense(struct scsi_sense_data *, int);
int scsi_running = 0;
struct pool scsi_xfer_pool;
+struct pool scsi_plug_pool;
+
+struct scsi_plug {
+ int target;
+ int lun;
+ int how;
+};
+
+void scsi_plug_probe(void *, void *);
+void scsi_plug_detach(void *, void *);
/*
* Called when a scsibus is attached to initialize global data.
@@ -84,6 +94,79 @@ scsi_init()
/* Initialize the scsi_xfer pool. */
pool_init(&scsi_xfer_pool, sizeof(struct scsi_xfer), 0,
0, 0, "scxspl", NULL);
+ /* Initialize the scsi_plug pool */
+ pool_init(&scsi_plug_pool, sizeof(struct scsi_plug), 0,
+ 0, 0, "scsiplug", NULL);
+ pool_setipl(&scsi_plug_pool, IPL_BIO);
+}
+
+int
+scsi_req_probe(struct scsibus_softc *sc, int target, int lun)
+{
+ struct scsi_plug *p;
+ int rv;
+
+ p = pool_get(&scsi_plug_pool, PR_NOWAIT);
+ if (p == NULL)
+ return (ENOMEM);
+
+ p->target = target;
+ p->lun = lun;
+
+ rv = workq_add_task(NULL, 0, scsi_plug_probe, sc, p);
+ if (rv != 0)
+ pool_put(&scsi_plug_pool, p);
+
+ return (rv);
+}
+
+int
+scsi_req_detach(struct scsibus_softc *sc, int target, int lun, int how)
+{
+ struct scsi_plug *p;
+ int rv;
+
+ p = pool_get(&scsi_plug_pool, PR_NOWAIT);
+ if (p == NULL)
+ return (ENOMEM);
+
+ p->target = target;
+ p->lun = lun;
+ p->how = how;
+
+ rv = workq_add_task(NULL, 0, scsi_plug_detach, sc, p);
+ if (rv != 0)
+ pool_put(&scsi_plug_pool, p);
+
+ return (rv);
+}
+
+void
+scsi_plug_probe(void *xsc, void *xp)
+{
+ struct scsibus_softc *sc = xsc;
+ struct scsi_plug *p = xp;
+
+ if (p->lun == -1)
+ scsi_probe_target(sc, p->target);
+ else
+ scsi_probe_lun(sc, p->target, p->lun);
+
+ pool_put(&scsi_plug_pool, p);
+}
+
+void
+scsi_plug_detach(void *xsc, void *xp)
+{
+ struct scsibus_softc *sc = xsc;
+ struct scsi_plug *p = xp;
+
+ if (p->lun == -1)
+ scsi_detach_target(sc, p->target, p->how);
+ else
+ scsi_detach_lun(sc, p->target, p->lun, p->how);
+
+ pool_put(&scsi_plug_pool, p);
}
void
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index 78deb047017..0723bcb73a7 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.h,v 1.99 2009/08/09 12:47:23 dlg Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.100 2009/08/13 19:49:31 dlg Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
@@ -554,6 +554,9 @@ int scsi_detach_bus(struct scsibus_softc *, int);
int scsi_detach_target(struct scsibus_softc *, int, int);
int scsi_detach_lun(struct scsibus_softc *, int, int, int);
+int scsi_req_probe(struct scsibus_softc *, int, int);
+int scsi_req_detach(struct scsibus_softc *, int, int, int);
+
extern const u_int8_t version_to_spc[];
#define SCSISPC(x)(version_to_spc[(x) & SID_ANSII])