summaryrefslogtreecommitdiff
path: root/sys
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 /sys
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.
Diffstat (limited to 'sys')
-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])