summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>1998-06-10 22:17:39 +0000
committerthorpej <thorpej@NetBSD.org>1998-06-10 22:17:39 +0000
commitb121e9e7727a2c28ea3cdb3595f3aa271c069bf0 (patch)
treee8ddb9e7da36c12980b4508c277d27bc752ef962 /sys/dev
parent7ea013ce828976fbb50800a5d48ef19721731992 (diff)
Add a shutdown hook for SCSI-2 and higher disks that issues a SYNCHRONIZE CACHE
operation with address 0 length 0, which, according to the SCSI-2 spec, should be interpreted as "synchronize all remaining blocks beginning at address 0".
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/scsipi/sd_scsi.c49
-rw-r--r--sys/dev/scsipi/sdvar.h4
2 files changed, 51 insertions, 2 deletions
diff --git a/sys/dev/scsipi/sd_scsi.c b/sys/dev/scsipi/sd_scsi.c
index 454aa402ca4..c630f101c74 100644
--- a/sys/dev/scsipi/sd_scsi.c
+++ b/sys/dev/scsipi/sd_scsi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sd_scsi.c,v 1.1 1998/01/15 02:21:40 cgd Exp $ */
+/* $NetBSD: sd_scsi.c,v 1.2 1998/06/10 22:17:39 thorpej Exp $ */
/*
* Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved.
@@ -103,6 +103,8 @@ const struct sd_ops sd_scsibus_ops = {
sd_scsibus_get_parms,
};
+static void sd_scsibus_shutdown __P((void *));
+
int
sd_scsibus_match(parent, match, aux)
struct device *parent;
@@ -150,6 +152,19 @@ sd_scsibus_attach(parent, self, aux)
sd->flags |= SDF_ANCIENT;
sdattach(parent, sd, sc_link, &sd_scsibus_ops);
+
+ /*
+ * Establish a shutdown hook so that we can ensure that
+ * our data has actually made it onto the platter at
+ * shutdown time. Note that this relies on the fact
+ * that the shutdown hook code puts us at the head of
+ * the list (thus guaranteeing that our hook runs before
+ * our ancestors').
+ */
+ if ((sd->sc_sdhook =
+ shutdownhook_establish(sd_scsibus_shutdown, sd)) == NULL)
+ printf("%s: WARNING: unable to establish shutdown hook\n",
+ sd->sc_dev.dv_xname);
}
static int
@@ -326,3 +341,35 @@ fake_it:
dp->disksize = sectors;
return (SDGP_RESULT_OK);
}
+
+static void
+sd_scsibus_shutdown(arg)
+ void *arg;
+{
+ struct sd_softc *sd = arg;
+ struct scsipi_link *sc_link = sd->sc_link;
+ struct scsi_synchronize_cache sync_cmd;
+
+ /*
+ * If the device is SCSI-2, issue a SYNCHRONIZE CACHE.
+ * We issue with address 0 length 0, which should be
+ * interpreted by the device as "all remaining blocks
+ * starting at address 0". We ignore ILLEGAL REQUEST
+ * in the event that the command is not supported by
+ * the device, and poll for completion so that we know
+ * that the cache has actually been flushed.
+ *
+ * XXX What about older devices?
+ */
+ if ((sc_link->scsipi_scsi.scsi_version & SID_ANSII) >= 2) {
+ bzero(&sync_cmd, sizeof(sync_cmd));
+ sync_cmd.opcode = SCSI_SYNCHRONIZE_CACHE;
+
+ if (scsipi_command(sc_link,
+ (struct scsipi_generic *)&sync_cmd, sizeof(sync_cmd),
+ NULL, 0, SDRETRIES, 100000, NULL,
+ SCSI_POLL|SCSI_IGNORE_ILLEGAL_REQUEST))
+ printf("%s: WARNING: cache synchronization failed\n",
+ sd->sc_dev.dv_xname);
+ }
+}
diff --git a/sys/dev/scsipi/sdvar.h b/sys/dev/scsipi/sdvar.h
index 90c00baa618..b7206aeb04f 100644
--- a/sys/dev/scsipi/sdvar.h
+++ b/sys/dev/scsipi/sdvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: sdvar.h,v 1.3 1998/02/13 08:28:57 enami Exp $ */
+/* $NetBSD: sdvar.h,v 1.4 1998/06/10 22:17:40 thorpej Exp $ */
/*
* Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved.
@@ -73,6 +73,8 @@ struct sd_softc {
u_int8_t type;
const struct sd_ops *sc_ops; /* our bus-dependent ops vector */
+ void *sc_sdhook; /* our shutdown hook */
+
#if NRND > 0
rndsource_element_t rnd_source;
#endif