Module Name: src
Committed By: mlelstv
Date: Sat Dec 10 10:26:38 UTC 2016
Modified Files:
src/sys/dev: files.dev
src/sys/dev/scsipi: cd.c cdvar.h sd.c sdvar.h
Log Message:
Refactored sd and cd to use common disk subroutines.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/files.dev
cvs rdiff -u -r1.333 -r1.334 src/sys/dev/scsipi/cd.c
cvs rdiff -u -r1.32 -r1.33 src/sys/dev/scsipi/cdvar.h
cvs rdiff -u -r1.319 -r1.320 src/sys/dev/scsipi/sd.c
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/scsipi/sdvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/files.dev
diff -u src/sys/dev/files.dev:1.1 src/sys/dev/files.dev:1.2
--- src/sys/dev/files.dev:1.1 Fri Aug 21 02:18:18 2015
+++ src/sys/dev/files.dev Sat Dec 10 10:26:38 2016
@@ -1,4 +1,4 @@
-# $NetBSD: files.dev,v 1.1 2015/08/21 02:18:18 uebayasi Exp $
+# $NetBSD: files.dev,v 1.2 2016/12/10 10:26:38 mlelstv Exp $
file dev/bio.c bio needs-flag
file dev/ccd.c ccd
@@ -6,7 +6,7 @@ file dev/cgd.c cgd
file dev/cgd_crypto.c cgd
file dev/clock_subr.c kern # XXX
file dev/clockctl.c clockctl
-file dev/dksubr.c cgd | xbd | ccd | raid | dm | ld
+file dev/dksubr.c cgd | xbd | ccd | raid | dm | ld | sd | cd
file dev/dkwedge/dk.c kern # XXX
file dev/dkwedge/dkwedge_apple.c dkwedge_method_apple
file dev/dkwedge/dkwedge_bsdlabel.c dkwedge_method_bsdlabel
Index: src/sys/dev/scsipi/cd.c
diff -u src/sys/dev/scsipi/cd.c:1.333 src/sys/dev/scsipi/cd.c:1.334
--- src/sys/dev/scsipi/cd.c:1.333 Sun Nov 20 15:37:19 2016
+++ src/sys/dev/scsipi/cd.c Sat Dec 10 10:26:38 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: cd.c,v 1.333 2016/11/20 15:37:19 mlelstv Exp $ */
+/* $NetBSD: cd.c,v 1.334 2016/12/10 10:26:38 mlelstv Exp $ */
/*-
* Copyright (c) 1998, 2001, 2003, 2004, 2005, 2008 The NetBSD Foundation,
@@ -50,7 +50,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.333 2016/11/20 15:37:19 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.334 2016/12/10 10:26:38 mlelstv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -114,22 +114,26 @@ struct cd_formatted_toc {
};
struct cdbounce {
- struct buf *obp; /* original buf */
- int doff; /* byte offset in orig. buf */
- int soff; /* byte offset in bounce buf */
- int resid; /* residual i/o in orig. buf */
- int bcount; /* actual obp bytes in bounce */
+ struct buf *obp; /* original buf */
+ struct buf *lbp; /* first buffer */
+ struct buf *rbp; /* second buffer */
+ int lerr; /* error returned for first buffer */
+ int rerr; /* error returned for second buffer */
+ int head; /* bytes skipped at the start */
+ int lcount; /* bytes copied to first buffer */
+ int rcount; /* bytes copied to second buffer */
};
static void cdstart(struct scsipi_periph *);
static void cdrestart(void *);
static void cdminphys(struct buf *);
-static void cdgetdefaultlabel(struct cd_softc *, struct cd_formatted_toc *,
- struct disklabel *);
-static void cdgetdisklabel(struct cd_softc *);
static void cddone(struct scsipi_xfer *, int);
-static void cdbounce(struct buf *);
static int cd_interpret_sense(struct scsipi_xfer *);
+static int cd_diskstart(device_t, struct buf *);
+static void cd_iosize(device_t, int *);
+static int cd_lastclose(device_t);
+static int cd_firstopen(device_t, dev_t, int, int);
+static void cd_label(device_t, struct disklabel *);
static u_long cd_size(struct cd_softc *, int);
static int cd_play(struct cd_softc *, int, int);
static int cd_play_tracks(struct cd_softc *, struct cd_formatted_toc *,
@@ -230,8 +234,14 @@ const struct cdevsw cd_cdevsw = {
};
static struct dkdriver cddkdriver = {
+ .d_open = cdopen,
+ .d_close = cdclose,
.d_strategy = cdstrategy,
- .d_minphys = cdminphys
+ .d_minphys = cdminphys,
+ .d_diskstart = cd_diskstart,
+ .d_firstopen = cd_firstopen,
+ .d_lastclose = cd_lastclose,
+ .d_label = cd_label,
};
static const struct scsipi_periphsw cd_switch = {
@@ -262,20 +272,37 @@ static void
cdattach(device_t parent, device_t self, void *aux)
{
struct cd_softc *cd = device_private(self);
+ struct dk_softc *dksc = &cd->sc_dksc;
struct scsipibus_attach_args *sa = aux;
struct scsipi_periph *periph = sa->sa_periph;
+ int dtype;
SC_DEBUG(periph, SCSIPI_DB2, ("cdattach: "));
- cd->sc_dev = self;
+ switch (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph))) {
+ case SCSIPI_BUSTYPE_SCSI:
+ dtype = DKTYPE_SCSI;
+ if (periph->periph_version == 0)
+ cd->flags |= CDF_ANCIENT;
+ break;
+ case SCSIPI_BUSTYPE_ATAPI:
+ dtype = DKTYPE_ATAPI;
+ break;
+ default:
+ dtype = DKTYPE_UNKNOWN;
+ break;
+ }
- mutex_init(&cd->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ /*
+ * Initialize and attach the disk structure.
+ */
+ dk_init(dksc, self, dtype);
+ disk_init(&dksc->sc_dkdev, dksc->sc_xname, &cddkdriver);
- if (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph)) ==
- SCSIPI_BUSTYPE_SCSI && periph->periph_version == 0)
- cd->flags |= CDF_ANCIENT;
+ dk_attach(dksc);
+ disk_attach(&dksc->sc_dkdev);
- bufq_alloc(&cd->buf_queue, "disksort", BUFQ_SORT_RAWBLOCK);
+ bufq_alloc(&dksc->sc_bufq, "disksort", BUFQ_SORT_RAWBLOCK);
callout_init(&cd->sc_callout, 0);
@@ -284,7 +311,7 @@ cdattach(device_t parent, device_t self,
*/
cd->sc_periph = periph;
- periph->periph_dev = cd->sc_dev;
+ periph->periph_dev = dksc->sc_dev;
periph->periph_switch = &cd_switch;
/*
@@ -296,17 +323,8 @@ cdattach(device_t parent, device_t self,
SCSIPI_CHAN_MAX_PERIPH(periph->periph_channel);
periph->periph_flags |= PERIPH_GROW_OPENINGS;
- /*
- * Initialize and attach the disk structure.
- */
- disk_init(&cd->sc_dk, device_xname(cd->sc_dev), &cddkdriver);
- disk_attach(&cd->sc_dk);
-
- aprint_normal("\n");
aprint_naive("\n");
-
- rnd_attach_source(&cd->rnd_source, device_xname(cd->sc_dev),
- RND_TYPE_DISK, RND_FLAG_DEFAULT);
+ aprint_normal("\n");
if (!pmf_device_register(self, NULL, NULL))
aprint_error_dev(self, "couldn't establish power handler\n");
@@ -316,16 +334,18 @@ static int
cddetach(device_t self, int flags)
{
struct cd_softc *cd = device_private(self);
+ struct dk_softc *dksc = &cd->sc_dksc;
struct scsipi_periph *periph = cd->sc_periph;
struct scsipi_channel *chan = periph->periph_channel;
- int bmaj, cmaj, i, mn;
+ int bmaj, cmaj, i, mn, rc;
- if (cd->sc_dk.dk_openmask != 0 && (flags & DETACH_FORCE) == 0)
- return EBUSY;
+ if ((rc = disk_begindetach(&dksc->sc_dkdev, cd_lastclose, self, flags)) != 0)
+ return rc;
/* locate the major number */
bmaj = bdevsw_lookup_major(&cd_bdevsw);
cmaj = cdevsw_lookup_major(&cd_cdevsw);
+
/* Nuke the vnodes for any open instances */
for (i = 0; i < MAXPARTITIONS; i++) {
mn = CDMINOR(device_unit(self), i);
@@ -336,183 +356,185 @@ cddetach(device_t self, int flags)
/* kill any pending restart */
callout_stop(&cd->sc_callout);
- mutex_enter(chan_mtx(chan));
-
- /* Kill off any queued buffers. */
- bufq_drain(cd->buf_queue);
+ dk_drain(dksc);
/* Kill off any pending commands. */
+ mutex_enter(chan_mtx(chan));
scsipi_kill_pending(cd->sc_periph);
-
mutex_exit(chan_mtx(chan));
- bufq_free(cd->buf_queue);
-
- mutex_destroy(&cd->sc_lock);
+ bufq_free(dksc->sc_bufq);
/* Detach from the disk list. */
- disk_detach(&cd->sc_dk);
- disk_destroy(&cd->sc_dk);
+ disk_detach(&dksc->sc_dkdev);
+ disk_destroy(&dksc->sc_dkdev);
+
+ dk_detach(dksc);
+
+ callout_destroy(&cd->sc_callout);
- /* Unhook the entropy source. */
- rnd_detach_source(&cd->rnd_source);
+ pmf_device_deregister(self);
return (0);
}
/*
+ * Serialized by caller
+ */
+static int
+cd_firstopen(device_t self, dev_t dev, int flag, int fmt)
+{
+ struct cd_softc *cd = device_private(self);
+ struct scsipi_periph *periph = cd->sc_periph;
+ struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
+ int error, silent;
+ int part;
+
+ part = CDPART(dev);
+
+ error = scsipi_adapter_addref(adapt);
+ if (error)
+ return error;
+
+ if ((part == RAW_PART && fmt == S_IFCHR) || (flag & FSILENT))
+ silent = XS_CTL_SILENT;
+ else
+ silent = 0;
+
+ /* make cdclose() loud again */
+ cd->flags &= ~CDF_EJECTED;
+
+ /* Check that it is still responding and ok. */
+ error = scsipi_test_unit_ready(periph,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
+ XS_CTL_SILENT);
+
+ /*
+ * Start the pack spinning if necessary. Always allow the
+ * raw parition to be opened, for raw IOCTLs. Data transfers
+ * will check for SDEV_MEDIA_LOADED.
+ */
+ if (error == EIO) {
+ error = scsipi_start(periph, SSS_START, silent);
+ if (error == EINVAL)
+ error = EIO;
+ }
+ if (error)
+ goto bad;
+
+ /* Lock the pack in. */
+ error = scsipi_prevent(periph, SPAMR_PREVENT_DT,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST |
+ XS_CTL_IGNORE_MEDIA_CHANGE);
+ SC_DEBUG(periph, SCSIPI_DB1,
+ ("cdopen: scsipi_prevent, error=%d\n", error));
+ if (error)
+ goto bad;
+
+ if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
+ int param_error;
+
+ /* Load the physical device parameters. */
+ param_error = cd_get_parms(cd, 0);
+ if (param_error == CDGP_RESULT_OFFLINE) {
+ error = ENXIO;
+ goto bad2;
+ }
+ periph->periph_flags |= PERIPH_MEDIA_LOADED;
+
+ SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
+
+ cd_set_geometry(cd);
+ }
+
+ periph->periph_flags |= PERIPH_OPEN;
+ return 0;
+
+bad2:
+ scsipi_prevent(periph, SPAMR_ALLOW,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST |
+ XS_CTL_IGNORE_MEDIA_CHANGE |
+ XS_CTL_SILENT);
+
+bad:
+ scsipi_adapter_delref(adapt);
+ return error;
+
+}
+
+/*
* open the device. Make sure the partition info is a up-to-date as can be.
*/
static int
cdopen(dev_t dev, int flag, int fmt, struct lwp *l)
{
struct cd_softc *cd;
+ struct dk_softc *dksc;
struct scsipi_periph *periph;
- struct scsipi_adapter *adapt;
- int part;
+ int unit, part;
int error;
- int rawpart;
- cd = device_lookup_private(&cd_cd, CDUNIT(dev));
+ unit = CDUNIT(dev);
+ cd = device_lookup_private(&cd_cd, unit);
if (cd == NULL)
return (ENXIO);
+ dksc = &cd->sc_dksc;
periph = cd->sc_periph;
- adapt = periph->periph_channel->chan_adapter;
part = CDPART(dev);
SC_DEBUG(periph, SCSIPI_DB1,
- ("cdopen: dev=0x%"PRIu64" (unit %"PRIu32" (of %d), partition %"PRId32")\n",dev,
- CDUNIT(dev), cd_cd.cd_ndevs, CDPART(dev)));
+ ("cdopen: dev=0x%"PRIu64" (unit %"PRIu32" (of %d), partition %d)\n",
+ dev, unit, cd_cd.cd_ndevs, CDPART(dev)));
/*
- * If this is the first open of this device, add a reference
- * to the adapter.
+ * If any partition is open, but the disk has been invalidated,
+ * disallow further opens of non-raw partition
*/
- if (cd->sc_dk.dk_openmask == 0 &&
- (error = scsipi_adapter_addref(adapt)) != 0)
- return (error);
-
- mutex_enter(&cd->sc_lock);
-
- rawpart = (part == RAW_PART && fmt == S_IFCHR);
- if ((periph->periph_flags & PERIPH_OPEN) != 0) {
- /*
- * If any partition is open, but the disk has been invalidated,
- * disallow further opens.
- */
- if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
- !rawpart) {
- error = EIO;
- goto bad3;
- }
- } else {
- /* Check that it is still responding and ok. */
- error = scsipi_test_unit_ready(periph,
- XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
- XS_CTL_SILENT);
-
- /*
- * Start the pack spinning if necessary. Always allow the
- * raw parition to be opened, for raw IOCTLs. Data transfers
- * will check for SDEV_MEDIA_LOADED.
- */
- if (error == EIO) {
- int error2;
- int silent;
+ if ((periph->periph_flags & (PERIPH_OPEN | PERIPH_MEDIA_LOADED)) ==
+ PERIPH_OPEN) {
+ if (part != RAW_PART || fmt != S_IFCHR)
+ return EIO;
+ }
- if (rawpart)
- silent = XS_CTL_SILENT;
- else
- silent = 0;
+ error = dk_open(dksc, dev, flag, fmt, l);
- error2 = scsipi_start(periph, SSS_START, silent);
- switch (error2) {
- case 0:
- error = 0;
- break;
- case EIO:
- case EINVAL:
- break;
- default:
- error = error2;
- break;
- }
- }
- if (error) {
- if (rawpart)
- goto out;
- goto bad3;
- }
+ SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
- periph->periph_flags |= PERIPH_OPEN;
-
- /* Lock the pack in. */
- error = scsipi_prevent(periph, SPAMR_PREVENT_DT,
- XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE);
- SC_DEBUG(periph, SCSIPI_DB1,
- ("cdopen: scsipi_prevent, error=%d\n", error));
- if (error) {
- if (rawpart)
- goto out;
- goto bad;
- }
+ return error;
+}
- if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
- /* Load the physical device parameters. */
- if (cd_get_parms(cd, 0) != 0) {
- if (rawpart)
- goto out;
- error = ENXIO;
- goto bad;
- }
- periph->periph_flags |= PERIPH_MEDIA_LOADED;
- SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
+/*
+ * Serialized by caller
+ */
+static int
+cd_lastclose(device_t self)
+{
+ struct cd_softc *cd = device_private(self);
+ struct scsipi_periph *periph = cd->sc_periph;
+ struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
+ int silent;
- /* Fabricate a disk label. */
- cdgetdisklabel(cd);
- SC_DEBUG(periph, SCSIPI_DB3, ("Disklabel fabricated "));
+ if (cd->flags & CDF_EJECTED)
+ silent = XS_CTL_SILENT;
+ else
+ silent = 0;
- cd_set_geometry(cd);
- }
- }
+ cdcachesync(periph, silent);
- /* Check that the partition exists. */
- if (part != RAW_PART &&
- (part >= cd->sc_dk.dk_label->d_npartitions ||
- cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
- error = ENXIO;
- goto bad;
- }
+ scsipi_wait_drain(periph);
-out: /* Insure only one open at a time. */
- switch (fmt) {
- case S_IFCHR:
- cd->sc_dk.dk_copenmask |= (1 << part);
- break;
- case S_IFBLK:
- cd->sc_dk.dk_bopenmask |= (1 << part);
- break;
- }
- cd->sc_dk.dk_openmask =
- cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
+ scsipi_prevent(periph, SPAMR_ALLOW,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST |
+ XS_CTL_IGNORE_NOT_READY |
+ XS_CTL_SILENT);
+ periph->periph_flags &= ~PERIPH_OPEN;
- SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
- mutex_exit(&cd->sc_lock);
- return (0);
+ scsipi_wait_drain(periph);
-bad:
- if (cd->sc_dk.dk_openmask == 0) {
- scsipi_prevent(periph, SPAMR_ALLOW,
- XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE);
- periph->periph_flags &= ~PERIPH_OPEN;
- }
+ scsipi_adapter_delref(adapt);
-bad3:
- mutex_exit(&cd->sc_lock);
- if (cd->sc_dk.dk_openmask == 0)
- scsipi_adapter_delref(adapt);
- return (error);
+ return 0;
}
/*
@@ -522,49 +544,149 @@ bad3:
static int
cdclose(dev_t dev, int flag, int fmt, struct lwp *l)
{
- struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(dev));
- struct scsipi_periph *periph = cd->sc_periph;
- struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
- int part = CDPART(dev);
- int silent = 0;
+ struct cd_softc *cd;
+ struct dk_softc *dksc;
+ int unit;
- if (part == RAW_PART && ((cd->sc_dk.dk_label->d_npartitions == 0) ||
- (part < cd->sc_dk.dk_label->d_npartitions &&
- cd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)))
- silent = XS_CTL_SILENT;
+ unit = CDUNIT(dev);
+ cd = device_lookup_private(&cd_cd, unit);
+ dksc = &cd->sc_dksc;
- mutex_enter(&cd->sc_lock);
+ return dk_close(dksc, dev, flag, fmt, l);
+}
- switch (fmt) {
- case S_IFCHR:
- cd->sc_dk.dk_copenmask &= ~(1 << part);
- break;
- case S_IFBLK:
- cd->sc_dk.dk_bopenmask &= ~(1 << part);
- break;
+static void
+cd_bounce_buffer_done(struct buf *bp)
+{
+ struct cdbounce *bounce = bp->b_private;
+ struct buf *obp = bounce->obp;
+
+ if (bp == bounce->lbp) {
+ if ((bounce->lerr = bp->b_error) == 0)
+ memcpy(obp->b_data, (char *)bp->b_data + bounce->head, bounce->lcount);
+ bounce->lbp = NULL;
}
- cd->sc_dk.dk_openmask =
- cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;
- if (cd->sc_dk.dk_openmask == 0) {
- /* synchronise caches on last close */
- cdcachesync(periph, silent);
+ if (bp == bounce->rbp) {
+ if ((bounce->rerr = bp->b_error) == 0)
+ memcpy((char *)obp->b_data + bounce->lcount, bp->b_data, bounce->rcount);
+ bounce->rbp = NULL;
+ }
- /* drain outstanding calls */
- scsipi_wait_drain(periph);
+ free(bp->b_data, M_DEVBUF);
+ putiobuf(bp);
- scsipi_prevent(periph, SPAMR_ALLOW,
- XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
- XS_CTL_IGNORE_NOT_READY | silent);
- periph->periph_flags &= ~PERIPH_OPEN;
+ if (bounce->lbp != NULL || bounce->rbp != NULL)
+ return;
- scsipi_wait_drain(periph);
+ obp->b_error = bounce->rerr;
+ if (bounce->lerr)
+ obp->b_error = bounce->lerr;
+
+ obp->b_resid = 0;
+ if (obp->b_error)
+ obp->b_resid = obp->b_bcount;
- scsipi_adapter_delref(adapt);
- }
+ free(bounce, M_DEVBUF);
+ biodone(obp);
+}
- mutex_exit(&cd->sc_lock);
- return (0);
+static int
+cd_make_bounce_buffer(struct cd_softc *cd, struct buf *bp, daddr_t blkno, int count, struct buf **nbpp, void *priv)
+{
+ struct buf *nbp;
+
+ /* We don't support bouncing writes */
+ if ((bp->b_flags & B_READ) == 0)
+ return EACCES; /* XXX */
+
+ nbp = getiobuf(NULL, false);
+ if (nbp == NULL)
+ return ENOMEM;
+
+ nbp->b_data = malloc(count, M_DEVBUF, M_NOWAIT);
+ if (nbp->b_data == NULL) {
+ putiobuf(nbp);
+ return ENOMEM;
+ }
+
+ /* Set up the IOP to the bounce buffer */
+ nbp->b_error = 0;
+ nbp->b_dev = bp->b_dev;
+ nbp->b_proc = bp->b_proc;
+ nbp->b_bcount = count;
+ nbp->b_bufsize = count;
+ nbp->b_blkno = blkno;
+ nbp->b_flags = bp->b_flags | B_READ;
+ nbp->b_oflags = bp->b_oflags;
+ nbp->b_cflags = bp->b_cflags;
+ nbp->b_iodone = cd_bounce_buffer_done;
+ nbp->b_private = priv;
+
+ BIO_COPYPRIO(nbp, bp);
+
+ *nbpp = nbp;
+ return 0;
+}
+
+static int
+cd_make_bounce(struct cd_softc *cd, struct buf *bp, struct cdbounce **bouncep)
+{
+ struct dk_softc *dksc = &cd->sc_dksc;
+ unsigned secsize = dksc->sc_dkdev.dk_geom.dg_secsize;
+ struct cdbounce *bounce;
+ int bps, nblks, skip, total, count;
+ daddr_t blkno;
+ struct buf *lbp, *rbp;
+ int error;
+
+ bounce = malloc(sizeof(struct cdbounce), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (bounce == NULL)
+ return ENOMEM;
+
+ bps = howmany(secsize, DEV_BSIZE);
+ nblks = howmany(bp->b_bcount, DEV_BSIZE);
+
+ skip = bp->b_blkno % bps;
+
+ blkno = bp->b_blkno - skip;
+ total = roundup(nblks + skip, bps) * DEV_BSIZE;
+
+ count = total;
+ cd_iosize(dksc->sc_dev, &count);
+
+ bounce->head = skip * DEV_BSIZE;
+ bounce->lcount = count - bounce->head;
+ bounce->rcount = bp->b_bcount - bounce->lcount;
+
+ error = cd_make_bounce_buffer(cd, bp, blkno, count, &lbp, bounce);
+ if (error)
+ goto bad;
+
+ blkno += howmany(count, DEV_BSIZE);
+ count = total - count;
+
+ if (count > 0) {
+ bounce->lbp->b_private = bounce;
+ error = cd_make_bounce_buffer(cd, bp, blkno, count, &rbp, bounce);
+ if (error) {
+ putiobuf(bounce->lbp);
+ goto bad;
+ }
+ } else
+ rbp = NULL;
+
+ bounce->obp = bp;
+ bounce->lbp = lbp;
+ bounce->rbp = rbp;
+
+ *bouncep = bounce;
+
+ return 0;
+
+bad:
+ free(bounce, M_DEVBUF);
+ return error;
}
/*
@@ -576,345 +698,220 @@ static void
cdstrategy(struct buf *bp)
{
struct cd_softc *cd = device_lookup_private(&cd_cd,CDUNIT(bp->b_dev));
- struct disklabel *lp;
+ struct dk_softc *dksc = &cd->sc_dksc;
struct scsipi_periph *periph = cd->sc_periph;
- struct scsipi_channel *chan = periph->periph_channel;
- daddr_t blkno;
+ int error;
SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdstrategy "));
SC_DEBUG(cd->sc_periph, SCSIPI_DB1,
("%d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
+
/*
* If the device has been made invalid, error out
* maybe the media changed
*/
if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
if (periph->periph_flags & PERIPH_OPEN)
- bp->b_error = EIO;
+ error = EIO;
else
- bp->b_error = ENODEV;
- goto done;
- }
-
- lp = cd->sc_dk.dk_label;
-
- /*
- * The transfer must be a whole number of blocks, offset must not
- * be negative.
- */
- if ((bp->b_bcount % lp->d_secsize) != 0 ||
- bp->b_blkno < 0 ) {
- bp->b_error = EINVAL;
- goto done;
- }
- /*
- * If it's a null transfer, return immediately
- */
- if (bp->b_bcount == 0)
- goto done;
-
- /*
- * Do bounds checking, adjust transfer. if error, process.
- * If end of partition, just return.
- */
- if (CDPART(bp->b_dev) == RAW_PART) {
- if (bounds_check_with_mediasize(bp, DEV_BSIZE,
- cd->params.disksize512) <= 0)
- goto done;
- } else {
- if (bounds_check_with_label(&cd->sc_dk, bp,
- (cd->flags & (CDF_WLABEL|CDF_LABELLING)) != 0) <= 0)
- goto done;
+ error = ENODEV;
+ goto bad;
}
/*
- * Now convert the block number to absolute and put it in
- * terms of the device's logical block size.
- */
- blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
- if (CDPART(bp->b_dev) != RAW_PART)
- blkno += lp->d_partitions[CDPART(bp->b_dev)].p_offset;
-
- bp->b_rawblkno = blkno;
-
- /*
- * If the disklabel sector size does not match the device
- * sector size we may need to do some extra work.
+ * If label and device don't agree in sector size use a bounce buffer
*/
- if (lp->d_secsize != cd->params.blksize) {
-
- /*
- * If the xfer is not a multiple of the device block size
- * or it is not block aligned, we need to bounce it.
- */
- if ((bp->b_bcount % cd->params.blksize) != 0 ||
- ((blkno * lp->d_secsize) % cd->params.blksize) != 0) {
- struct cdbounce *bounce;
- struct buf *nbp;
- long count;
-
- if ((bp->b_flags & B_READ) == 0) {
-
- /* XXXX We don't support bouncing writes. */
- bp->b_error = EACCES;
- goto done;
- }
-
- bounce = malloc(sizeof(*bounce), M_DEVBUF, M_NOWAIT);
- if (!bounce) {
- /* No memory -- fail the iop. */
- bp->b_error = ENOMEM;
- goto done;
- }
+ if (dksc->sc_dkdev.dk_label->d_secsize != dksc->sc_dkdev.dk_geom.dg_secsize) {
+ struct cdbounce *bounce;
- bounce->obp = bp;
- bounce->resid = bp->b_bcount;
- bounce->doff = 0;
- count = ((blkno * lp->d_secsize) % cd->params.blksize);
- bounce->soff = count;
- count += bp->b_bcount;
- count = roundup(count, cd->params.blksize);
- bounce->bcount = bounce->resid;
- if (count > MAXPHYS) {
- bounce->bcount = MAXPHYS - bounce->soff;
- count = MAXPHYS;
- }
-
- blkno = ((blkno * lp->d_secsize) / cd->params.blksize);
- nbp = getiobuf(NULL, false);
- if (!nbp) {
- /* No memory -- fail the iop. */
- free(bounce, M_DEVBUF);
- bp->b_error = ENOMEM;
- goto done;
- }
- nbp->b_data = malloc(count, M_DEVBUF, M_NOWAIT);
- if (!nbp->b_data) {
- /* No memory -- fail the iop. */
- free(bounce, M_DEVBUF);
- putiobuf(nbp);
- bp->b_error = ENOMEM;
- goto done;
- }
-
- /* Set up the IOP to the bounce buffer. */
- nbp->b_error = 0;
- nbp->b_proc = bp->b_proc;
- nbp->b_bcount = count;
- nbp->b_bufsize = count;
- nbp->b_rawblkno = blkno;
- nbp->b_flags = bp->b_flags | B_READ;
- nbp->b_oflags = bp->b_oflags;
- nbp->b_cflags = bp->b_cflags;
- nbp->b_iodone = cdbounce;
-
- /* store bounce state in b_private and use new buf */
- nbp->b_private = bounce;
-
- BIO_COPYPRIO(nbp, bp);
+ error = cd_make_bounce(cd, bp, &bounce);
+ if (error)
+ goto bad;
- bp = nbp;
+ dk_strategy(dksc, bounce->lbp);
+ if (bounce->rbp != NULL)
+ dk_strategy(dksc, bounce->rbp);
- } else {
- /* Xfer is aligned -- just adjust the start block */
- bp->b_rawblkno = (blkno * lp->d_secsize) /
- cd->params.blksize;
- }
+ return;
}
- mutex_enter(chan_mtx(chan));
-
- /*
- * Place it in the queue of disk activities for this disk.
- *
- * XXX Only do disksort() if the current operating mode does not
- * XXX include tagged queueing.
- */
- bufq_put(cd->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- cdstart(periph);
-
- mutex_exit(chan_mtx(chan));
+
+ dk_strategy(dksc, bp);
return;
-done:
- /*
- * Correctly set the buf to indicate a completed xfer
- */
+bad:
+ bp->b_error = error;
bp->b_resid = bp->b_bcount;
biodone(bp);
}
/*
- * cdstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It deques the buf and creates a scsi command to perform the
- * transfer in the buf. The transfer request will call scsipi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (cdstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
+ * Issue single I/O command
*
- * must be called with channel lock held
- * cdstart() is called from cdstrategy, cdrestart and scsipi_done
+ * Called from dk_start and implicitely from dk_strategy
*/
-static void
-cdstart(struct scsipi_periph *periph)
+static int
+cd_diskstart(device_t dev, struct buf *bp)
{
- struct cd_softc *cd = device_private(periph->periph_dev);
- struct buf *bp = 0;
+ struct cd_softc *cd = device_private(dev);
+ struct scsipi_periph *periph = cd->sc_periph;
+ struct scsipi_channel *chan = periph->periph_channel;
struct scsipi_rw_10 cmd_big;
struct scsi_rw_6 cmd_small;
struct scsipi_generic *cmdp;
struct scsipi_xfer *xs;
- int flags, nblks, cmdlen, error __diagused;
+ int error, flags, nblks, cmdlen;
SC_DEBUG(periph, SCSIPI_DB2, ("cdstart "));
+ mutex_enter(chan_mtx(chan));
+
+ if (periph->periph_active >= periph->periph_openings) {
+ error = EAGAIN;
+ goto out;
+ }
+
/*
- * Check if the device has room for another command
+ * there is excess capacity, but a special waits
+ * It'll need the adapter as soon as we clear out of the
+ * way and let it run (user level wait).
+ */
+ if (periph->periph_flags & PERIPH_WAITING) {
+ periph->periph_flags &= ~PERIPH_WAITING;
+ cv_broadcast(periph_cv_periph(periph));
+ error = EAGAIN;
+ goto out;
+ }
+
+ /*
+ * If the device has become invalid, abort all the
+ * reads and writes until all files have been closed and
+ * re-opened
*/
- while (periph->periph_active < periph->periph_openings) {
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (periph->periph_flags & PERIPH_WAITING) {
- periph->periph_flags &= ~PERIPH_WAITING;
- cv_broadcast(periph_cv_periph(periph));
- return;
- }
+ if (__predict_false(
+ (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) {
+ error = EIO;
+ goto out;
+ }
- /*
- * If the device has become invalid, abort all the
- * reads and writes until all files have been closed and
- * re-opened
- */
- if (__predict_false(
- (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) {
- if ((bp = bufq_get(cd->buf_queue)) != NULL) {
- bp->b_error = EIO;
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- continue;
- } else {
- return;
- }
- }
+ nblks = howmany(bp->b_bcount, cd->params.blksize);
+ /*
+ * Fill out the scsi command. If the transfer will
+ * fit in a "small" cdb, use it.
+ */
+ if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
+ ((nblks & 0xff) == nblks) &&
+ !(periph->periph_quirks & PQUIRK_ONLYBIG)) {
/*
- * See if there is a buf with work for us to do..
+ * We can fit in a small cdb.
*/
- if ((bp = bufq_peek(cd->buf_queue)) == NULL)
- return;
-
+ memset(&cmd_small, 0, sizeof(cmd_small));
+ cmd_small.opcode = (bp->b_flags & B_READ) ?
+ SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND;
+ _lto3b(bp->b_rawblkno, cmd_small.addr);
+ cmd_small.length = nblks & 0xff;
+ cmdlen = sizeof(cmd_small);
+ cmdp = (struct scsipi_generic *)&cmd_small;
+ } else {
/*
- * We have a buf, now we should make a command.
+ * Need a large cdb.
*/
+ memset(&cmd_big, 0, sizeof(cmd_big));
+ cmd_big.opcode = (bp->b_flags & B_READ) ?
+ READ_10 : WRITE_10;
+ _lto4b(bp->b_rawblkno, cmd_big.addr);
+ _lto2b(nblks, cmd_big.length);
+ cmdlen = sizeof(cmd_big);
+ cmdp = (struct scsipi_generic *)&cmd_big;
+ }
- nblks = howmany(bp->b_bcount, cd->params.blksize);
+ /*
+ * Figure out what flags to use.
+ */
+ flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
+ if (bp->b_flags & B_READ)
+ flags |= XS_CTL_DATA_IN;
+ else
+ flags |= XS_CTL_DATA_OUT;
+ /*
+ * Call the routine that chats with the adapter.
+ * Note: we cannot sleep as we may be an interrupt
+ */
+ xs = scsipi_make_xs_locked(periph, cmdp, cmdlen,
+ (u_char *)bp->b_data, bp->b_bcount,
+ CDRETRIES, 30000, bp, flags);
+ if (__predict_false(xs == NULL)) {
/*
- * Fill out the scsi command. If the transfer will
- * fit in a "small" cdb, use it.
+ * out of memory. Keep this buffer in the queue, and
+ * retry later.
*/
- if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
- ((nblks & 0xff) == nblks) &&
- !(periph->periph_quirks & PQUIRK_ONLYBIG)) {
- /*
- * We can fit in a small cdb.
- */
- memset(&cmd_small, 0, sizeof(cmd_small));
- cmd_small.opcode = (bp->b_flags & B_READ) ?
- SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND;
- _lto3b(bp->b_rawblkno, cmd_small.addr);
- cmd_small.length = nblks & 0xff;
- cmdlen = sizeof(cmd_small);
- cmdp = (struct scsipi_generic *)&cmd_small;
- } else {
- /*
- * Need a large cdb.
- */
- memset(&cmd_big, 0, sizeof(cmd_big));
- cmd_big.opcode = (bp->b_flags & B_READ) ?
- READ_10 : WRITE_10;
- _lto4b(bp->b_rawblkno, cmd_big.addr);
- _lto2b(nblks, cmd_big.length);
- cmdlen = sizeof(cmd_big);
- cmdp = (struct scsipi_generic *)&cmd_big;
- }
+ callout_reset(&cd->sc_callout, hz / 2, cdrestart,
+ periph);
+ error = 0;
+ goto out;
+ }
- /* Instrumentation. */
- disk_busy(&cd->sc_dk);
+ error = scsipi_execute_xs(xs);
+ /* with a scsipi_xfer preallocated, scsipi_command can't fail */
+ KASSERT(error == 0);
- /*
- * Figure out what flags to use.
- */
- flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
- if (bp->b_flags & B_READ)
- flags |= XS_CTL_DATA_IN;
- else
- flags |= XS_CTL_DATA_OUT;
+out:
+ mutex_exit(chan_mtx(chan));
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- xs = scsipi_make_xs_locked(periph, cmdp, cmdlen,
- (u_char *)bp->b_data, bp->b_bcount,
- CDRETRIES, 30000, bp, flags);
- if (__predict_false(xs == NULL)) {
- /*
- * out of memory. Keep this buffer in the queue, and
- * retry later.
- */
- callout_reset(&cd->sc_callout, hz / 2, cdrestart,
- periph);
- return;
- }
- /*
- * need to dequeue the buffer before queuing the command,
- * because cdstart may be called recursively from the
- * HBA driver
- */
-#ifdef DIAGNOSTIC
- if (bufq_get(cd->buf_queue) != bp)
- panic("cdstart(): dequeued wrong buf");
-#else
- bufq_get(cd->buf_queue);
-#endif
- error = scsipi_execute_xs(xs);
- /* with a scsipi_xfer preallocated, scsipi_command can't fail */
- KASSERT(error == 0);
- }
+ return error;
}
+/*
+ * Recover I/O request after memory shortage
+ *
+ * Called from callout
+ */
static void
cdrestart(void *v)
{
- struct scsipi_periph *periph = (struct scsipi_periph *)v;
+ struct cd_softc *cd = v;
+ struct dk_softc *dksc = &cd->sc_dksc;
+
+ dk_start(dksc, NULL);
+}
+
+/*
+ * Recover I/O request after memory shortage
+ *
+ * Called from scsipi midlayer when resources have been freed
+ * with channel lock held
+ */
+static void
+cdstart(struct scsipi_periph *periph)
+{
+ struct cd_softc *cd = device_private(periph->periph_dev);
+ struct dk_softc *dksc = &cd->sc_dksc;
struct scsipi_channel *chan = periph->periph_channel;
- mutex_enter(chan_mtx(chan));
- cdstart((struct scsipi_periph *)v);
+ /*
+ * release channel lock as dk_start may need to acquire
+ * other locks
+ *
+ * cdstart is called from scsipi_put_xs and all its callers
+ * release the lock afterwards. So releasing it here
+ * doesn't matter.
+ */
mutex_exit(chan_mtx(chan));
+
+ dk_start(dksc, NULL);
+
+ mutex_enter(chan_mtx(chan));
}
static void
cddone(struct scsipi_xfer *xs, int error)
{
struct cd_softc *cd = device_private(xs->xs_periph->periph_dev);
+ struct dk_softc *dksc = &cd->sc_dksc;
struct buf *bp = xs->bp;
if (bp) {
- /* note, bp->b_resid is NOT initialised */
bp->b_error = error;
bp->b_resid = xs->resid;
if (error) {
@@ -922,102 +919,10 @@ cddone(struct scsipi_xfer *xs, int error
bp->b_resid = bp->b_bcount;
}
- disk_unbusy(&cd->sc_dk, bp->b_bcount - bp->b_resid,
- (bp->b_flags & B_READ));
- rnd_add_uint32(&cd->rnd_source, bp->b_rawblkno);
-
- biodone(bp);
+ dk_done(dksc, bp);
}
}
-static void
-cdbounce(struct buf *bp)
-{
- struct cdbounce *bounce = (struct cdbounce *)bp->b_private;
- struct buf *obp = bounce->obp;
- struct cd_softc *cd =
- device_lookup_private(&cd_cd, CDUNIT(obp->b_dev));
- struct disklabel *lp = cd->sc_dk.dk_label;
-
- if (bp->b_error != 0) {
- /* EEK propagate the error and free the memory */
- goto done;
- }
-
- KASSERT(obp->b_flags & B_READ);
-
- /* copy bounce buffer to final destination */
- memcpy((char *)obp->b_data + bounce->doff,
- (char *)bp->b_data + bounce->soff, bounce->bcount);
-
- /* check if we need more I/O, i.e. bounce put us over MAXPHYS */
- KASSERT(bounce->resid >= bounce->bcount);
- bounce->resid -= bounce->bcount;
- if (bounce->resid > 0) {
- struct buf *nbp;
- daddr_t blkno;
- long count;
-
- blkno = obp->b_rawblkno +
- ((obp->b_bcount - bounce->resid) / lp->d_secsize);
- count = ((blkno * lp->d_secsize) % cd->params.blksize);
- blkno = (blkno * lp->d_secsize) / cd->params.blksize;
- bounce->soff = count;
- bounce->doff += bounce->bcount;
- count += bounce->resid;
- count = roundup(count, cd->params.blksize);
- bounce->bcount = bounce->resid;
- if (count > MAXPHYS) {
- bounce->bcount = MAXPHYS - bounce->soff;
- count = MAXPHYS;
- }
-
- nbp = getiobuf(NULL, false);
- if (!nbp) {
- /* No memory -- fail the iop. */
- bp->b_error = ENOMEM;
- goto done;
- }
-
- /* Set up the IOP to the bounce buffer. */
- nbp->b_error = 0;
- nbp->b_proc = obp->b_proc;
- nbp->b_bcount = count;
- nbp->b_bufsize = count;
- nbp->b_data = bp->b_data;
- nbp->b_rawblkno = blkno;
- nbp->b_flags = obp->b_flags | B_READ;
- nbp->b_oflags = obp->b_oflags;
- nbp->b_cflags = obp->b_cflags;
- nbp->b_iodone = cdbounce;
-
- /* store bounce state in b_private and use new buf */
- nbp->b_private = bounce;
-
- BIO_COPYPRIO(nbp, obp);
-
- bp->b_data = NULL;
- putiobuf(bp);
-
- /* enqueue the request and return */
- mutex_enter(chan_mtx(cd->sc_periph->periph_channel));
- bufq_put(cd->buf_queue, nbp);
- cdstart(cd->sc_periph);
- mutex_exit(chan_mtx(cd->sc_periph->periph_channel));
-
- return;
- }
-
-done:
- obp->b_error = bp->b_error;
- obp->b_resid = bp->b_resid;
- free(bp->b_data, M_DEVBUF);
- free(bounce, M_DEVBUF);
- bp->b_data = NULL;
- putiobuf(bp);
- biodone(obp);
-}
-
static int
cd_interpret_sense(struct scsipi_xfer *xs)
{
@@ -1105,6 +1010,7 @@ static void
cdminphys(struct buf *bp)
{
struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(bp->b_dev));
+ struct dk_softc *dksc = &cd->sc_dksc;
long xmax;
/*
@@ -1119,13 +1025,28 @@ cdminphys(struct buf *bp)
* in a 10-byte read/write actually means 0 blocks.
*/
if (cd->flags & CDF_ANCIENT) {
- xmax = cd->sc_dk.dk_label->d_secsize * 0xff;
+ xmax = dksc->sc_dkdev.dk_geom.dg_secsize * 0xff;
if (bp->b_bcount > xmax)
bp->b_bcount = xmax;
}
- (*cd->sc_periph->periph_channel->chan_adapter->adapt_minphys)(bp);
+ scsipi_adapter_minphys(cd->sc_periph->periph_channel, bp);
+}
+
+static void
+cd_iosize(device_t dev, int *count)
+{
+ struct buf B;
+ int bmaj;
+
+ bmaj = bdevsw_lookup_major(&cd_bdevsw);
+ B.b_dev = MAKECDDEV(bmaj,device_unit(dev),RAW_PART);
+ B.b_bcount = *count;
+
+ cdminphys(&B);
+
+ *count = B.b_bcount;
}
static int
@@ -1201,7 +1122,7 @@ cdreadmsaddr(struct cd_softc *cd, struct
return 0;
}
-/* synchronise caches code from sd.c, move to scsipi_ioctl.c ? */
+/* synchronise caches code from cd.c, move to scsipi_ioctl.c ? */
static int
cdcachesync(struct scsipi_periph *periph, int flags) {
struct scsi_synchronize_cache_10 cmd;
@@ -1271,13 +1192,11 @@ static int
cdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
struct cd_softc *cd = device_lookup_private(&cd_cd, CDUNIT(dev));
+ struct dk_softc *dksc = &cd->sc_dksc;
struct scsipi_periph *periph = cd->sc_periph;
struct cd_formatted_toc toc;
int part = CDPART(dev);
int error;
-#ifdef __HAVE_OLD_DISKLABEL
- struct disklabel *newlabel = NULL;
-#endif
SC_DEBUG(cd->sc_periph, SCSIPI_DB2, ("cdioctl 0x%lx ", cmd));
@@ -1285,128 +1204,11 @@ cdioctl(dev_t dev, u_long cmd, void *add
* If the device is not valid, some IOCTLs can still be
* handled on the raw partition. Check this here.
*/
- if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
- switch (cmd) {
- case DIOCWLABEL:
- case DIOCLOCK:
- case ODIOCEJECT:
- case DIOCEJECT:
- case DIOCCACHESYNC:
- case DIOCTUR:
- case SCIOCIDENTIFY:
- case OSCIOCIDENTIFY:
- case SCIOCCOMMAND:
- case SCIOCDEBUG:
- case CDIOCGETVOL:
- case CDIOCSETVOL:
- case CDIOCSETMONO:
- case CDIOCSETSTEREO:
- case CDIOCSETMUTE:
- case CDIOCSETLEFT:
- case CDIOCSETRIGHT:
- case CDIOCCLOSE:
- case CDIOCEJECT:
- case CDIOCALLOW:
- case CDIOCPREVENT:
- case CDIOCSETDEBUG:
- case CDIOCCLRDEBUG:
- case CDIOCRESET:
- case SCIOCRESET:
- case CDIOCLOADUNLOAD:
- case DVD_AUTH:
- case DVD_READ_STRUCT:
- case DIOCGSTRATEGY:
- case DIOCSSTRATEGY:
- if (part == RAW_PART)
- break;
- /* FALLTHROUGH */
- default:
- if ((periph->periph_flags & PERIPH_OPEN) == 0)
- return (ENODEV);
- else
- return (EIO);
- }
- }
-
- error = disk_ioctl(&cd->sc_dk, dev, cmd, addr, flag, l);
- if (error != EPASSTHROUGH)
- return (error);
+ if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
+ part != RAW_PART)
+ return (EIO);
- error = 0;
switch (cmd) {
- case DIOCWDINFO:
- case DIOCSDINFO:
-#ifdef __HAVE_OLD_DISKLABEL
- case ODIOCWDINFO:
- case ODIOCSDINFO:
-#endif
- {
- struct disklabel *lp;
-
- if ((flag & FWRITE) == 0)
- return (EBADF);
-
-#ifdef __HAVE_OLD_DISKLABEL
- if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
- newlabel = malloc(sizeof (*newlabel), M_TEMP,
- M_WAITOK | M_ZERO);
- if (newlabel == NULL)
- return (EIO);
- memcpy(newlabel, addr, sizeof (struct olddisklabel));
- lp = newlabel;
- } else
-#endif
- lp = addr;
-
- mutex_enter(&cd->sc_lock);
- cd->flags |= CDF_LABELLING;
-
- error = setdisklabel(cd->sc_dk.dk_label,
- lp, /*cd->sc_dk.dk_openmask : */0,
- cd->sc_dk.dk_cpulabel);
- if (error == 0) {
- /* XXX ? */
- }
-
- cd->flags &= ~CDF_LABELLING;
- mutex_exit(&cd->sc_lock);
-#ifdef __HAVE_OLD_DISKLABEL
- if (newlabel != NULL)
- free(newlabel, M_TEMP);
-#endif
- return (error);
- }
-
- case DIOCWLABEL:
- return (EBADF);
-
- case DIOCGDEFLABEL:
- cdgetdefaultlabel(cd, &toc, addr);
- return (0);
-
-#ifdef __HAVE_OLD_DISKLABEL
- case ODIOCGDEFLABEL:
- newlabel = malloc(sizeof (*newlabel), M_TEMP, M_WAITOK);
- if (newlabel == NULL)
- return (EIO);
- cdgetdefaultlabel(cd, &toc, newlabel);
- if (newlabel->d_npartitions > OLDMAXPARTITIONS)
- error = ENOTTY;
- else
- memcpy(addr, newlabel, sizeof (struct olddisklabel));
- free(newlabel, M_TEMP);
- return error;
-#endif
-
- case DIOCTUR: {
- /* test unit ready */
- error = scsipi_test_unit_ready(cd->sc_periph, XS_CTL_SILENT);
- *((int*)addr) = (error == 0);
- if (error == ENODEV || error == EIO || error == 0)
- return 0;
- return error;
- }
-
case CDIOCPLAYTRACKS: {
/* PLAY_MSF command */
struct ioc_play_track *args = addr;
@@ -1557,13 +1359,12 @@ cdioctl(dev_t dev, u_long cmd, void *add
XS_CTL_IGNORE_NOT_READY | XS_CTL_IGNORE_MEDIA_CHANGE));
case DIOCEJECT:
if (*(int *)addr == 0) {
+ int pmask = 1 << part;
/*
* Don't force eject: check that we are the only
* partition open. If so, unlock it.
*/
- if ((cd->sc_dk.dk_openmask & ~(1 << part)) == 0 &&
- cd->sc_dk.dk_bopenmask + cd->sc_dk.dk_copenmask ==
- cd->sc_dk.dk_openmask) {
+ if (DK_BUSY(dksc, pmask) == 0) {
error = scsipi_prevent(periph, SPAMR_ALLOW,
XS_CTL_IGNORE_NOT_READY);
if (error)
@@ -1576,22 +1377,9 @@ cdioctl(dev_t dev, u_long cmd, void *add
case CDIOCEJECT: /* FALLTHROUGH */
case ODIOCEJECT:
error = scsipi_start(periph, SSS_STOP|SSS_LOEJ, 0);
- if (error == 0) {
- int i;
-
- /*
- * We have just successfully ejected the medium,
- * all partitions cached are meaningless now.
- * Make sure cdclose() will do silent operations
- * now by marking all partitions unused.
- * Before any real access, a new (default-)disk-
- * label will be generated anyway.
- */
- for (i = 0; i < cd->sc_dk.dk_label->d_npartitions;
- i++)
- cd->sc_dk.dk_label->d_partitions[i].p_fstype =
- FS_UNUSED;
- }
+ if (error == 0)
+ /* Make sure cdclose() will do silent operations */
+ cd->flags |= CDF_EJECTED;
return error;
case DIOCCACHESYNC:
/* SYNCHRONISE CACHES command */
@@ -1639,51 +1427,11 @@ cdioctl(dev_t dev, u_long cmd, void *add
case MMCSETUPWRITEPARAMS :
/* MODE SENSE page 5, MODE_SELECT page 5 commands */
return mmc_setup_writeparams(periph, (struct mmc_writeparams *) addr);
- case DIOCGSTRATEGY:
- {
- struct disk_strategy *dks = addr;
- int s;
-
- s = splbio();
- strlcpy(dks->dks_name, bufq_getstrategyname(cd->buf_queue),
- sizeof(dks->dks_name));
- splx(s);
- dks->dks_paramlen = 0;
-
- return 0;
- }
- case DIOCSSTRATEGY:
- {
- struct disk_strategy *dks = addr;
- struct bufq_state *new;
- struct bufq_state *old;
- int s;
-
- if ((flag & FWRITE) == 0) {
- return EBADF;
- }
- if (dks->dks_param != NULL) {
- return EINVAL;
- }
- dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
- error = bufq_alloc(&new, dks->dks_name,
- BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
- if (error) {
- return error;
- }
- s = splbio();
- old = cd->buf_queue;
- bufq_move(new, old);
- cd->buf_queue = new;
- splx(s);
- bufq_free(old);
-
- return 0;
- }
default:
- if (part != RAW_PART)
- return (ENOTTY);
- return (scsipi_do_ioctl(periph, dev, cmd, addr, flag, l));
+ error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
+ if (error == ENOTTY)
+ error = scsipi_do_ioctl(periph, dev, cmd, addr, flag, l);
+ return (error);
}
#ifdef DIAGNOSTIC
@@ -1692,40 +1440,17 @@ cdioctl(dev_t dev, u_long cmd, void *add
}
static void
-cdgetdefaultlabel(struct cd_softc *cd, struct cd_formatted_toc *toc,
- struct disklabel *lp)
+cd_label(device_t self, struct disklabel *lp)
{
+ struct cd_softc *cd = device_private(self);
+ struct cd_formatted_toc toc;
int lastsession;
- memset(lp, 0, sizeof(struct disklabel));
-
- lp->d_secsize = cd->params.blksize;
- lp->d_ntracks = 1;
- lp->d_nsectors = 100;
- lp->d_ncylinders = (cd->params.disksize / 100) + 1;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-
- switch (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(cd->sc_periph))) {
- case SCSIPI_BUSTYPE_SCSI:
- lp->d_type = DKTYPE_SCSI;
- break;
- case SCSIPI_BUSTYPE_ATAPI:
- lp->d_type = DKTYPE_ATAPI;
- break;
- }
- /*
- * XXX
- * We could probe the mode pages to figure out what kind of disc it is.
- * Is this worthwhile?
- */
strncpy(lp->d_typename, "optical media", 16);
- strncpy(lp->d_packname, "fictitious", 16);
- lp->d_secperunit = cd->params.disksize;
lp->d_rpm = 300;
- lp->d_interleave = 1;
- lp->d_flags = D_REMOVABLE | D_SCSI_MMC;
+ lp->d_flags |= D_REMOVABLE | D_SCSI_MMC;
- if (cdreadmsaddr(cd, toc, &lastsession) != 0)
+ if (cdreadmsaddr(cd, &toc, &lastsession) != 0)
lastsession = 0;
lp->d_partitions[0].p_offset = 0;
@@ -1736,51 +1461,6 @@ cdgetdefaultlabel(struct cd_softc *cd, s
lp->d_partitions[RAW_PART].p_offset = 0;
lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
lp->d_partitions[RAW_PART].p_fstype = FS_UDF;
-
- lp->d_npartitions = RAW_PART + 1;
-
- lp->d_magic = DISKMAGIC;
- lp->d_magic2 = DISKMAGIC;
- lp->d_checksum = dkcksum(lp);
-}
-
-/*
- * Load the label information on the named device
- * Actually fabricate a disklabel
- *
- * EVENTUALLY take information about different
- * data tracks from the TOC and put it in the disklabel
- */
-static void
-cdgetdisklabel(struct cd_softc *cd)
-{
- struct disklabel *lp = cd->sc_dk.dk_label;
- struct cd_formatted_toc toc;
- const char *errstring;
- int bmajor;
-
- memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
-
- cdgetdefaultlabel(cd, &toc, lp);
-
- /*
- * Call the generic disklabel extraction routine
- *
- * bmajor follows ata_raid code
- */
- bmajor = devsw_name2blk(device_xname(cd->sc_dev), NULL, 0);
- errstring = readdisklabel(MAKECDDEV(bmajor,
- device_unit(cd->sc_dev), RAW_PART),
- cdstrategy, lp, cd->sc_dk.dk_cpulabel);
-
- /* if all went OK, we are passed a NULL error string */
- if (errstring == NULL)
- return;
-
- /* Reset to default label -- after printing error and the warning */
- aprint_error_dev(cd->sc_dev, "%s\n", errstring);
- memset(cd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
- cdgetdefaultlabel(cd, &toc, lp);
}
/*
@@ -3920,12 +3600,15 @@ mmc_setup_writeparams(struct scsipi_peri
static void
cd_set_geometry(struct cd_softc *cd)
{
- struct disk_geom *dg = &cd->sc_dk.dk_geom;
+ struct dk_softc *dksc = &cd->sc_dksc;
+ struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
memset(dg, 0, sizeof(*dg));
dg->dg_secperunit = cd->params.disksize;
dg->dg_secsize = cd->params.blksize;
+ dg->dg_nsectors = 100;
+ dg->dg_ntracks = 1;
- disk_set_info(cd->sc_dev, &cd->sc_dk, NULL);
+ disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
}
Index: src/sys/dev/scsipi/cdvar.h
diff -u src/sys/dev/scsipi/cdvar.h:1.32 src/sys/dev/scsipi/cdvar.h:1.33
--- src/sys/dev/scsipi/cdvar.h:1.32 Tue Apr 14 20:32:36 2015
+++ src/sys/dev/scsipi/cdvar.h Sat Dec 10 10:26:38 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: cdvar.h,v 1.32 2015/04/14 20:32:36 riastradh Exp $ */
+/* $NetBSD: cdvar.h,v 1.33 2016/12/10 10:26:38 mlelstv Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer. All rights reserved.
@@ -24,19 +24,16 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/rndsource.h>
+#include <dev/dkvar.h>
#define CDRETRIES 4
struct cd_softc {
- device_t sc_dev;
- struct disk sc_dk;
- kmutex_t sc_lock;
+ struct dk_softc sc_dksc;
int flags;
-#define CDF_WLABEL 0x04 /* label is writable */
-#define CDF_LABELLING 0x08 /* writing label */
#define CDF_ANCIENT 0x10 /* disk is ancient; for minphys */
+#define CDF_EJECTED 0x20 /* be silent when flushing cache */
struct scsipi_periph *sc_periph;
@@ -46,8 +43,9 @@ struct cd_softc {
u_long disksize512; /* total number sectors */
} params;
- struct bufq_state *buf_queue;
struct callout sc_callout;
-
- krndsource_t rnd_source;
};
+
+#define CDGP_RESULT_OK 0 /* parameters obtained */
+#define CDGP_RESULT_OFFLINE 1 /* no media, or otherwise losing */
+#define CDGP_RESULT_UNFORMATTED 2 /* unformatted media (max params) */
Index: src/sys/dev/scsipi/sd.c
diff -u src/sys/dev/scsipi/sd.c:1.319 src/sys/dev/scsipi/sd.c:1.320
--- src/sys/dev/scsipi/sd.c:1.319 Sun Nov 20 15:37:19 2016
+++ src/sys/dev/scsipi/sd.c Sat Dec 10 10:26:38 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: sd.c,v 1.319 2016/11/20 15:37:19 mlelstv Exp $ */
+/* $NetBSD: sd.c,v 1.320 2016/12/10 10:26:38 mlelstv Exp $ */
/*-
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -47,14 +47,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.319 2016/11/20 15:37:19 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.320 2016/12/10 10:26:38 mlelstv Exp $");
#ifdef _KERNEL_OPT
#include "opt_scsi.h"
#endif
-#define SD_MPSAFE D_MPSAFE
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -73,7 +71,6 @@ __KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.319
#include <sys/proc.h>
#include <sys/conf.h>
#include <sys/vnode.h>
-#include <sys/rndsource.h>
#include <dev/scsipi/scsi_spc.h>
#include <dev/scsipi/scsipi_all.h>
@@ -96,15 +93,18 @@ __KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.319
#define SD_DEFAULT_BLKSIZE 512
static void sdminphys(struct buf *);
-static void sdgetdefaultlabel(struct sd_softc *, struct disklabel *);
-static int sdgetdisklabel(struct sd_softc *);
static void sdstart(struct scsipi_periph *);
static void sdrestart(void *);
static void sddone(struct scsipi_xfer *, int);
static bool sd_suspend(device_t, const pmf_qual_t *);
static bool sd_shutdown(device_t, int);
static int sd_interpret_sense(struct scsipi_xfer *);
-static int sdlastclose(device_t);
+static int sd_diskstart(device_t, struct buf *);
+static int sd_dumpblocks(device_t, void *, daddr_t, int);
+static void sd_iosize(device_t, int *);
+static int sd_lastclose(device_t);
+static int sd_firstopen(device_t, dev_t, int, int);
+static void sd_label(device_t, struct disklabel *);
static int sd_mode_sense(struct sd_softc *, u_int8_t, void *, size_t, int,
int, int *);
@@ -167,7 +167,7 @@ const struct bdevsw sd_bdevsw = {
.d_dump = sddump,
.d_psize = sdsize,
.d_discard = nodiscard,
- .d_flag = D_DISK | SD_MPSAFE
+ .d_flag = D_DISK | D_MPSAFE
};
const struct cdevsw sd_cdevsw = {
@@ -182,12 +182,20 @@ const struct cdevsw sd_cdevsw = {
.d_mmap = nommap,
.d_kqfilter = nokqfilter,
.d_discard = nodiscard,
- .d_flag = D_DISK | SD_MPSAFE
+ .d_flag = D_DISK | D_MPSAFE
};
static struct dkdriver sddkdriver = {
+ .d_open = sdopen,
+ .d_close = sdclose,
.d_strategy = sdstrategy,
- .d_minphys = sdminphys
+ .d_minphys = sdminphys,
+ .d_diskstart = sd_diskstart,
+ .d_dumpblocks = sd_dumpblocks,
+ .d_iosize = sd_iosize,
+ .d_firstopen = sd_firstopen,
+ .d_lastclose = sd_lastclose,
+ .d_label = sd_label,
};
static const struct scsipi_periphsw sd_switch = {
@@ -236,25 +244,44 @@ static void
sdattach(device_t parent, device_t self, void *aux)
{
struct sd_softc *sd = device_private(self);
+ struct dk_softc *dksc = &sd->sc_dksc;
struct scsipibus_attach_args *sa = aux;
struct scsipi_periph *periph = sa->sa_periph;
- int error, result;
+ int error, result, dtype;
struct disk_parms *dp = &sd->params;
char pbuf[9];
SC_DEBUG(periph, SCSIPI_DB2, ("sdattach: "));
- sd->sc_dev = self;
sd->type = (sa->sa_inqbuf.type & SID_TYPE);
strncpy(sd->name, sa->sa_inqbuf.product, sizeof(sd->name));
+
if (sd->type == T_SIMPLE_DIRECT)
periph->periph_quirks |= PQUIRK_ONLYBIG | PQUIRK_NOBIGMODESENSE;
- if (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph)) ==
- SCSIPI_BUSTYPE_SCSI && periph->periph_version == 0)
- sd->flags |= SDF_ANCIENT;
+ switch (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sa->sa_periph))) {
+ case SCSIPI_BUSTYPE_SCSI:
+ dtype = DKTYPE_SCSI;
+ if (periph->periph_version == 0)
+ sd->flags |= SDF_ANCIENT;
+ break;
+ case SCSIPI_BUSTYPE_ATAPI:
+ dtype = DKTYPE_ATAPI;
+ break;
+ default:
+ dtype = DKTYPE_UNKNOWN;
+ break;
+ }
+
+ /* Initialize dk and disk structure. */
+ dk_init(dksc, self, dtype);
+ disk_init(&dksc->sc_dkdev, dksc->sc_xname, &sddkdriver);
+
+ /* Attach dk and disk subsystems */
+ dk_attach(dksc);
+ disk_attach(&dksc->sc_dkdev);
- bufq_alloc(&sd->buf_queue, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
+ bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
callout_init(&sd->sc_callout, 0);
@@ -263,7 +290,7 @@ sdattach(device_t parent, device_t self,
*/
sd->sc_periph = periph;
- periph->periph_dev = sd->sc_dev;
+ periph->periph_dev = dksc->sc_dev;
periph->periph_switch = &sd_switch;
/*
@@ -276,12 +303,6 @@ sdattach(device_t parent, device_t self,
periph->periph_flags |= PERIPH_GROW_OPENINGS;
/*
- * Initialize and attach the disk structure.
- */
- disk_init(&sd->sc_dk, device_xname(sd->sc_dev), &sddkdriver);
- disk_attach(&sd->sc_dk);
-
- /*
* Use the subdriver to request information regarding the drive.
*/
aprint_naive("\n");
@@ -293,12 +314,12 @@ sdattach(device_t parent, device_t self,
error = scsipi_test_unit_ready(periph,
XS_CTL_DISCOVERY | XS_CTL_IGNORE_ILLEGAL_REQUEST |
XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_SILENT_NODEV);
-
if (error)
result = SDGP_RESULT_OFFLINE;
else
result = sd_get_parms(sd, &sd->params, XS_CTL_DISCOVERY);
- aprint_normal_dev(sd->sc_dev, "");
+
+ aprint_normal_dev(dksc->sc_dev, "");
switch (result) {
case SDGP_RESULT_OK:
format_bytes(pbuf, sizeof(pbuf),
@@ -325,6 +346,9 @@ sdattach(device_t parent, device_t self,
}
aprint_normal("\n");
+ /* Discover wedges on this disk. */
+ dkwedge_discover(&dksc->sc_dkdev);
+
/*
* Establish a shutdown hook so that we can ensure that
* our data has actually made it onto the platter at
@@ -335,36 +359,18 @@ sdattach(device_t parent, device_t self,
*/
if (!pmf_device_register1(self, sd_suspend, NULL, sd_shutdown))
aprint_error_dev(self, "couldn't establish power handler\n");
-
- /*
- * attach the device into the random source list
- */
- rnd_attach_source(&sd->rnd_source, device_xname(sd->sc_dev),
- RND_TYPE_DISK, RND_FLAG_DEFAULT);
-
- /* Discover wedges on this disk. */
- dkwedge_discover(&sd->sc_dk);
-
- /*
- * Disk insertion and removal times can be a useful source
- * of entropy, though the estimator should never _count_
- * these bits, on insertion, because the deltas to the
- * nonexistent) previous event should never allow it.
- */
- rnd_add_uint32(&sd->rnd_source, 0);
}
static int
sddetach(device_t self, int flags)
{
struct sd_softc *sd = device_private(self);
+ struct dk_softc *dksc = &sd->sc_dksc;
struct scsipi_periph *periph = sd->sc_periph;
struct scsipi_channel *chan = periph->periph_channel;
int bmaj, cmaj, i, mn, rc;
- rnd_add_uint32(&sd->rnd_source, 0);
-
- if ((rc = disk_begindetach(&sd->sc_dk, sdlastclose, self, flags)) != 0)
+ if ((rc = disk_begindetach(&dksc->sc_dkdev, sd_lastclose, self, flags)) != 0)
return rc;
/* locate the major number */
@@ -381,227 +387,172 @@ sddetach(device_t self, int flags)
/* kill any pending restart */
callout_stop(&sd->sc_callout);
- /* Delete all of our wedges. */
- dkwedge_delall(&sd->sc_dk);
-
- mutex_enter(chan_mtx(chan));
-
- /* Kill off any queued buffers. */
- bufq_drain(sd->buf_queue);
+ dk_drain(dksc);
/* Kill off any pending commands. */
- scsipi_kill_pending(sd->sc_periph);
-
+ mutex_enter(chan_mtx(chan));
+ scsipi_kill_pending(periph);
mutex_exit(chan_mtx(chan));
- bufq_free(sd->buf_queue);
+ bufq_free(dksc->sc_bufq);
+
+ /* Delete all of our wedges. */
+ dkwedge_delall(&dksc->sc_dkdev);
/* Detach from the disk list. */
- disk_detach(&sd->sc_dk);
- disk_destroy(&sd->sc_dk);
+ disk_detach(&dksc->sc_dkdev);
+ disk_destroy(&dksc->sc_dkdev);
+
+ dk_detach(dksc);
callout_destroy(&sd->sc_callout);
pmf_device_deregister(self);
- /* Unhook the entropy source. */
- rnd_detach_source(&sd->rnd_source);
-
return (0);
}
/*
- * open the device. Make sure the partition info is a up-to-date as can be.
+ * Serialized by caller
*/
static int
-sdopen(dev_t dev, int flag, int fmt, struct lwp *l)
+sd_firstopen(device_t self, dev_t dev, int flag, int fmt)
{
- struct sd_softc *sd;
- struct scsipi_periph *periph;
- struct scsipi_adapter *adapt;
- int unit, part;
- int error;
+ struct sd_softc *sd = device_private(self);
+ struct scsipi_periph *periph = sd->sc_periph;
+ struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
+ int error, silent;
+ int part, removable;
- unit = SDUNIT(dev);
- sd = device_lookup_private(&sd_cd, unit);
- if (sd == NULL)
- return (ENXIO);
+ part = SDPART(dev);
- if (!device_is_active(sd->sc_dev))
- return (ENODEV);
+ error = scsipi_adapter_addref(adapt);
+ if (error)
+ return error;
- part = SDPART(dev);
+ if ((part == RAW_PART && fmt == S_IFCHR) || (flag & FSILENT))
+ silent = XS_CTL_SILENT;
+ else
+ silent = 0;
- mutex_enter(&sd->sc_dk.dk_openlock);
+ /* Check that it is still responding and ok. */
+ error = scsipi_test_unit_ready(periph,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
+ silent);
/*
- * If there are wedges, and this is not RAW_PART, then we
- * need to fail.
+ * Start the pack spinning if necessary. Always allow the
+ * raw parition to be opened, for raw IOCTLs. Data transfers
+ * will check for SDEV_MEDIA_LOADED.
*/
- if (sd->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
- error = EBUSY;
- goto bad1;
+ if (error == EIO) {
+ error = scsipi_start(periph, SSS_START, silent);
+ if (error == EINVAL)
+ error = EIO;
}
+ if (error)
+ goto bad;
- periph = sd->sc_periph;
- adapt = periph->periph_channel->chan_adapter;
-
- SC_DEBUG(periph, SCSIPI_DB1,
- ("sdopen: dev=0x%"PRIx64" (unit %d (of %d), partition %d)\n", dev, unit,
- sd_cd.cd_ndevs, part));
+ removable = (periph->periph_flags & PERIPH_REMOVABLE) != 0;
+ if (removable) {
+ /* Lock the pack in. */
+ error = scsipi_prevent(periph, SPAMR_PREVENT_DT,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST |
+ XS_CTL_IGNORE_MEDIA_CHANGE |
+ XS_CTL_SILENT);
+ if (error)
+ goto bad;
+ }
- /*
- * If this is the first open of this device, add a reference
- * to the adapter.
- */
- if (sd->sc_dk.dk_openmask == 0 &&
- (error = scsipi_adapter_addref(adapt)) != 0)
- goto bad1;
+ if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
+ int param_error;
- if ((periph->periph_flags & PERIPH_OPEN) != 0) {
/*
- * If any partition is open, but the disk has been invalidated,
- * disallow further opens of non-raw partition
+ * Load the physical device parameters.
+ *
+ * Note that if media is present but unformatted,
+ * we allow the open (so that it can be formatted!).
+ * The drive should refuse real I/O, if the media is
+ * unformatted.
*/
- if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
- (part != RAW_PART || fmt != S_IFCHR)) {
- error = EIO;
+ param_error = sd_get_parms(sd, &sd->params, 0);
+ if (param_error == SDGP_RESULT_OFFLINE) {
+ error = ENXIO;
goto bad2;
}
- } else {
- int silent;
+ periph->periph_flags |= PERIPH_MEDIA_LOADED;
- if ((part == RAW_PART && fmt == S_IFCHR) || (flag & FSILENT))
- silent = XS_CTL_SILENT;
- else
- silent = 0;
+ SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
+ }
- /* Check that it is still responding and ok. */
- error = scsipi_test_unit_ready(periph,
- XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_MEDIA_CHANGE |
- silent);
+ periph->periph_flags |= PERIPH_OPEN;
+ return 0;
- /*
- * Start the pack spinning if necessary. Always allow the
- * raw parition to be opened, for raw IOCTLs. Data transfers
- * will check for SDEV_MEDIA_LOADED.
- */
- if (error == EIO) {
- int error2;
+bad2:
+ if (removable)
+ scsipi_prevent(periph, SPAMR_ALLOW,
+ XS_CTL_IGNORE_ILLEGAL_REQUEST |
+ XS_CTL_IGNORE_MEDIA_CHANGE |
+ XS_CTL_SILENT);
- error2 = scsipi_start(periph, SSS_START, silent);
- switch (error2) {
- case 0:
- error = 0;
- break;
- case EIO:
- case EINVAL:
- break;
- default:
- error = error2;
- break;
- }
- }
- if (error) {
- if (silent && (flag & FSILENT) == 0)
- goto out;
- goto bad2;
- }
+bad:
+ scsipi_adapter_delref(adapt);
+ return error;
+}
- periph->periph_flags |= PERIPH_OPEN;
+/*
+ * open the device. Make sure the partition info is a up-to-date as can be.
+ */
+static int
+sdopen(dev_t dev, int flag, int fmt, struct lwp *l)
+{
+ struct sd_softc *sd;
+ struct dk_softc *dksc;
+ struct scsipi_periph *periph;
+ int unit, part;
+ int error;
- if (periph->periph_flags & PERIPH_REMOVABLE) {
- /* Lock the pack in. */
- error = scsipi_prevent(periph, SPAMR_PREVENT_DT,
- XS_CTL_IGNORE_ILLEGAL_REQUEST |
- XS_CTL_IGNORE_MEDIA_CHANGE |
- XS_CTL_SILENT);
- if (error)
- goto bad3;
- }
+ unit = SDUNIT(dev);
+ sd = device_lookup_private(&sd_cd, unit);
+ if (sd == NULL)
+ return (ENXIO);
+ dksc = &sd->sc_dksc;
- if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
- int param_error;
- periph->periph_flags |= PERIPH_MEDIA_LOADED;
+ if (!device_is_active(dksc->sc_dev))
+ return (ENODEV);
- /*
- * Load the physical device parameters.
- *
- * Note that if media is present but unformatted,
- * we allow the open (so that it can be formatted!).
- * The drive should refuse real I/O, if the media is
- * unformatted.
- */
- if ((param_error = sd_get_parms(sd, &sd->params, 0))
- == SDGP_RESULT_OFFLINE) {
- error = ENXIO;
- periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
- goto bad3;
- }
- SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
+ periph = sd->sc_periph;
+ part = SDPART(dev);
- /* Load the partition info if not already loaded. */
- if (param_error == 0) {
- if ((sdgetdisklabel(sd) != 0) && (part != RAW_PART)) {
- error = EIO;
- goto bad3;
- }
- SC_DEBUG(periph, SCSIPI_DB3,
- ("Disklabel loaded "));
- }
- }
- }
+ SC_DEBUG(periph, SCSIPI_DB1,
+ ("sdopen: dev=0x%"PRIx64" (unit %d (of %d), partition %d)\n",
+ dev, unit, sd_cd.cd_ndevs, SDPART(dev)));
- /* Check that the partition exists. */
- if (part != RAW_PART &&
- (part >= sd->sc_dk.dk_label->d_npartitions ||
- sd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
- error = ENXIO;
- goto bad3;
+ /*
+ * If any partition is open, but the disk has been invalidated,
+ * disallow further opens of non-raw partition
+ */
+ if ((periph->periph_flags & (PERIPH_OPEN | PERIPH_MEDIA_LOADED)) ==
+ PERIPH_OPEN) {
+ if (part != RAW_PART || fmt != S_IFCHR)
+ return EIO;
}
- out: /* Insure only one open at a time. */
- switch (fmt) {
- case S_IFCHR:
- sd->sc_dk.dk_copenmask |= (1 << part);
- break;
- case S_IFBLK:
- sd->sc_dk.dk_bopenmask |= (1 << part);
- break;
- }
- sd->sc_dk.dk_openmask =
- sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
+ error = dk_open(dksc, dev, flag, fmt, l);
SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
- mutex_exit(&sd->sc_dk.dk_openlock);
- return (0);
- bad3:
- if (sd->sc_dk.dk_openmask == 0) {
- if (periph->periph_flags & PERIPH_REMOVABLE)
- scsipi_prevent(periph, SPAMR_ALLOW,
- XS_CTL_IGNORE_ILLEGAL_REQUEST |
- XS_CTL_IGNORE_MEDIA_CHANGE |
- XS_CTL_SILENT);
- periph->periph_flags &= ~PERIPH_OPEN;
- }
-
- bad2:
- if (sd->sc_dk.dk_openmask == 0)
- scsipi_adapter_delref(adapt);
-
- bad1:
- mutex_exit(&sd->sc_dk.dk_openlock);
- return (error);
+ return error;
}
/*
- * Caller must hold sd->sc_dk.dk_openlock.
+ * Serialized by caller
*/
static int
-sdlastclose(device_t self)
+sd_lastclose(device_t self)
{
struct sd_softc *sd = device_private(self);
+ struct dk_softc *dksc = &sd->sc_dksc;
struct scsipi_periph *periph = sd->sc_periph;
struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
@@ -611,7 +562,7 @@ sdlastclose(device_t self)
*/
if ((sd->flags & SDF_DIRTY) != 0) {
if (sd_flush(sd, 0)) {
- aprint_error_dev(sd->sc_dev,
+ aprint_error_dev(dksc->sc_dev,
"cache synchronization failed\n");
sd->flags &= ~SDF_FLUSHING;
} else
@@ -641,26 +592,15 @@ sdlastclose(device_t self)
static int
sdclose(dev_t dev, int flag, int fmt, struct lwp *l)
{
- struct sd_softc *sd = device_lookup_private(&sd_cd, SDUNIT(dev));
- int part = SDPART(dev);
-
- mutex_enter(&sd->sc_dk.dk_openlock);
- switch (fmt) {
- case S_IFCHR:
- sd->sc_dk.dk_copenmask &= ~(1 << part);
- break;
- case S_IFBLK:
- sd->sc_dk.dk_bopenmask &= ~(1 << part);
- break;
- }
- sd->sc_dk.dk_openmask =
- sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
+ struct sd_softc *sd;
+ struct dk_softc *dksc;
+ int unit;
- if (sd->sc_dk.dk_openmask == 0)
- sdlastclose(sd->sc_dev);
+ unit = SDUNIT(dev);
+ sd = device_lookup_private(&sd_cd, unit);
+ dksc = &sd->sc_dksc;
- mutex_exit(&sd->sc_dk.dk_openlock);
- return (0);
+ return dk_close(dksc, dev, flag, fmt, l);
}
/*
@@ -672,285 +612,209 @@ static void
sdstrategy(struct buf *bp)
{
struct sd_softc *sd = device_lookup_private(&sd_cd, SDUNIT(bp->b_dev));
+ struct dk_softc *dksc = &sd->sc_dksc;
struct scsipi_periph *periph = sd->sc_periph;
- struct scsipi_channel *chan = periph->periph_channel;
- struct disklabel *lp;
- daddr_t blkno;
- bool sector_aligned;
SC_DEBUG(sd->sc_periph, SCSIPI_DB2, ("sdstrategy "));
SC_DEBUG(sd->sc_periph, SCSIPI_DB1,
("%d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
+
/*
* If the device has been made invalid, error out
*/
if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 ||
- !device_is_active(sd->sc_dev)) {
+ !device_is_active(dksc->sc_dev)) {
if (periph->periph_flags & PERIPH_OPEN)
bp->b_error = EIO;
else
bp->b_error = ENODEV;
- goto done;
+
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+ return;
}
- lp = sd->sc_dk.dk_label;
+ dk_strategy(dksc, bp);
+}
+
+/*
+ * Issue single I/O command
+ *
+ * Called from dk_start and implicitely from dk_strategy
+ */
+static int
+sd_diskstart(device_t dev, struct buf *bp)
+{
+ struct sd_softc *sd = device_private(dev);
+ struct scsipi_periph *periph = sd->sc_periph;
+ struct scsipi_channel *chan = periph->periph_channel;
+ struct scsipi_rw_16 cmd16;
+ struct scsipi_rw_10 cmd_big;
+ struct scsi_rw_6 cmd_small;
+ struct scsipi_generic *cmdp;
+ struct scsipi_xfer *xs;
+ int error, flags, nblks, cmdlen;
+
+ mutex_enter(chan_mtx(chan));
+
+ if (periph->periph_active >= periph->periph_openings) {
+ error = EAGAIN;
+ goto out;
+ }
/*
- * The transfer must be a whole number of blocks, offset must not be
- * negative.
- */
- if (lp->d_secsize == DEV_BSIZE) {
- sector_aligned = (bp->b_bcount & (DEV_BSIZE - 1)) == 0;
- } else {
- sector_aligned = (bp->b_bcount % lp->d_secsize) == 0;
+ * there is excess capacity, but a special waits
+ * It'll need the adapter as soon as we clear out of the
+ * way and let it run (user level wait).
+ */
+ if (periph->periph_flags & PERIPH_WAITING) {
+ periph->periph_flags &= ~PERIPH_WAITING;
+ cv_broadcast(periph_cv_periph(periph));
+ error = EAGAIN;
+ goto out;
}
- if (!sector_aligned || bp->b_blkno < 0) {
- bp->b_error = EINVAL;
- goto done;
+
+ /*
+ * If the device has become invalid, abort all the
+ * reads and writes until all files have been closed and
+ * re-opened
+ */
+ if (__predict_false(
+ (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) {
+ error = EIO;
+ goto out;
}
+
/*
- * If it's a null transfer, return immediatly
+ * Mark the disk dirty so that the cache will be
+ * flushed on close.
*/
- if (bp->b_bcount == 0)
- goto done;
+ if ((bp->b_flags & B_READ) == 0)
+ sd->flags |= SDF_DIRTY;
+
+ if (sd->params.blksize == DEV_BSIZE)
+ nblks = bp->b_bcount >> DEV_BSHIFT;
+ else
+ nblks = howmany(bp->b_bcount, sd->params.blksize);
/*
- * Do bounds checking, adjust transfer. if error, process.
- * If end of partition, just return.
+ * Fill out the scsi command. Use the smallest CDB possible
+ * (6-byte, 10-byte, or 16-byte).
*/
- if (SDPART(bp->b_dev) == RAW_PART) {
- if (bounds_check_with_mediasize(bp, DEV_BSIZE,
- sd->params.disksize512) <= 0)
- goto done;
+ if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
+ ((nblks & 0xff) == nblks) &&
+ !(periph->periph_quirks & PQUIRK_ONLYBIG)) {
+ /* 6-byte CDB */
+ memset(&cmd_small, 0, sizeof(cmd_small));
+ cmd_small.opcode = (bp->b_flags & B_READ) ?
+ SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND;
+ _lto3b(bp->b_rawblkno, cmd_small.addr);
+ cmd_small.length = nblks & 0xff;
+ cmdlen = sizeof(cmd_small);
+ cmdp = (struct scsipi_generic *)&cmd_small;
+ } else if ((bp->b_rawblkno & 0xffffffff) == bp->b_rawblkno) {
+ /* 10-byte CDB */
+ memset(&cmd_big, 0, sizeof(cmd_big));
+ cmd_big.opcode = (bp->b_flags & B_READ) ?
+ READ_10 : WRITE_10;
+ _lto4b(bp->b_rawblkno, cmd_big.addr);
+ _lto2b(nblks, cmd_big.length);
+ cmdlen = sizeof(cmd_big);
+ cmdp = (struct scsipi_generic *)&cmd_big;
} else {
- if (bounds_check_with_label(&sd->sc_dk, bp,
- (sd->flags & (SDF_WLABEL|SDF_LABELLING)) != 0) <= 0)
- goto done;
+ /* 16-byte CDB */
+ memset(&cmd16, 0, sizeof(cmd16));
+ cmd16.opcode = (bp->b_flags & B_READ) ?
+ READ_16 : WRITE_16;
+ _lto8b(bp->b_rawblkno, cmd16.addr);
+ _lto4b(nblks, cmd16.length);
+ cmdlen = sizeof(cmd16);
+ cmdp = (struct scsipi_generic *)&cmd16;
}
/*
- * Now convert the block number to absolute and put it in
- * terms of the device's logical block size.
- */
- if (lp->d_secsize == DEV_BSIZE)
- blkno = bp->b_blkno;
- else if (lp->d_secsize > DEV_BSIZE)
- blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
+ * Figure out what flags to use.
+ */
+ flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
+ if (bp->b_flags & B_READ)
+ flags |= XS_CTL_DATA_IN;
else
- blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
-
- if (SDPART(bp->b_dev) != RAW_PART)
- blkno += lp->d_partitions[SDPART(bp->b_dev)].p_offset;
-
- bp->b_rawblkno = blkno;
-
- mutex_enter(chan_mtx(chan));
+ flags |= XS_CTL_DATA_OUT;
/*
- * Place it in the queue of disk activities for this disk.
- *
- * XXX Only do disksort() if the current operating mode does not
- * XXX include tagged queueing.
+ * Call the routine that chats with the adapter.
+ * Note: we cannot sleep as we may be an interrupt
*/
- bufq_put(sd->buf_queue, bp);
+ xs = scsipi_make_xs_locked(periph, cmdp, cmdlen,
+ (u_char *)bp->b_data, bp->b_bcount,
+ SDRETRIES, SD_IO_TIMEOUT, bp, flags);
+ if (__predict_false(xs == NULL)) {
+ /*
+ * out of memory. Keep this buffer in the queue, and
+ * retry later.
+ */
+ callout_reset(&sd->sc_callout, hz / 2, sdrestart, sd);
+ error = 0;
+ goto out;
+ }
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- sdstart(periph);
+ error = scsipi_execute_xs(xs);
+ /* with a scsipi_xfer preallocated, scsipi_command can't fail */
+ KASSERT(error == 0);
+out:
mutex_exit(chan_mtx(chan));
- return;
-done:
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
+ return error;
}
/*
- * sdstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer in the buf. The transfer request will call scsipi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (sdstrategy)
+ * Recover I/O request after memory shortage
*
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
+ * Called from callout
+ */
+static void
+sdrestart(void *v)
+{
+ struct sd_softc *sd = v;
+ struct dk_softc *dksc = &sd->sc_dksc;
+
+ dk_start(dksc, NULL);
+}
+
+/*
+ * Recover I/O request after memory shortage
*
- * must be called with channel lock held
- * sdstart() is called from sdstrategy, sdrestart and scsipi_done
+ * Called from scsipi midlayer when resources have been freed
+ * with channel lock held
*/
static void
sdstart(struct scsipi_periph *periph)
{
struct sd_softc *sd = device_private(periph->periph_dev);
- struct disklabel *lp = sd->sc_dk.dk_label;
- struct buf *bp = 0;
- struct scsipi_rw_16 cmd16;
- struct scsipi_rw_10 cmd_big;
- struct scsi_rw_6 cmd_small;
- struct scsipi_generic *cmdp;
- struct scsipi_xfer *xs;
- int nblks, cmdlen, error __diagused, flags;
-
- SC_DEBUG(periph, SCSIPI_DB2, ("sdstart "));
+ struct dk_softc *dksc = &sd->sc_dksc;
+ struct scsipi_channel *chan = periph->periph_channel;
/*
- * Check if the device has room for another command
+ * release channel lock as dk_start may need to acquire
+ * other locks
+ *
+ * sdstart is called from scsipi_put_xs and all its callers
+ * release the lock afterwards. So releasing it here
+ * doesn't matter.
*/
- while (periph->periph_active < periph->periph_openings) {
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (periph->periph_flags & PERIPH_WAITING) {
- periph->periph_flags &= ~PERIPH_WAITING;
- cv_broadcast(periph_cv_periph(periph));
- return;
- }
-
- /*
- * If the device has become invalid, abort all the
- * reads and writes until all files have been closed and
- * re-opened
- */
- if (__predict_false(
- (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)) {
- if ((bp = bufq_get(sd->buf_queue)) != NULL) {
- bp->b_error = EIO;
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- continue;
- } else {
- return;
- }
- }
-
- /*
- * See if there is a buf with work for us to do..
- */
- if ((bp = bufq_peek(sd->buf_queue)) == NULL)
- return;
-
- /*
- * We have a buf, now we should make a command.
- */
-
- if (lp->d_secsize == DEV_BSIZE)
- nblks = bp->b_bcount >> DEV_BSHIFT;
- else
- nblks = howmany(bp->b_bcount, lp->d_secsize);
-
- /*
- * Fill out the scsi command. Use the smallest CDB possible
- * (6-byte, 10-byte, or 16-byte).
- */
- if (((bp->b_rawblkno & 0x1fffff) == bp->b_rawblkno) &&
- ((nblks & 0xff) == nblks) &&
- !(periph->periph_quirks & PQUIRK_ONLYBIG)) {
- /* 6-byte CDB */
- memset(&cmd_small, 0, sizeof(cmd_small));
- cmd_small.opcode = (bp->b_flags & B_READ) ?
- SCSI_READ_6_COMMAND : SCSI_WRITE_6_COMMAND;
- _lto3b(bp->b_rawblkno, cmd_small.addr);
- cmd_small.length = nblks & 0xff;
- cmdlen = sizeof(cmd_small);
- cmdp = (struct scsipi_generic *)&cmd_small;
- } else if ((bp->b_rawblkno & 0xffffffff) == bp->b_rawblkno) {
- /* 10-byte CDB */
- memset(&cmd_big, 0, sizeof(cmd_big));
- cmd_big.opcode = (bp->b_flags & B_READ) ?
- READ_10 : WRITE_10;
- _lto4b(bp->b_rawblkno, cmd_big.addr);
- _lto2b(nblks, cmd_big.length);
- cmdlen = sizeof(cmd_big);
- cmdp = (struct scsipi_generic *)&cmd_big;
- } else {
- /* 16-byte CDB */
- memset(&cmd16, 0, sizeof(cmd16));
- cmd16.opcode = (bp->b_flags & B_READ) ?
- READ_16 : WRITE_16;
- _lto8b(bp->b_rawblkno, cmd16.addr);
- _lto4b(nblks, cmd16.length);
- cmdlen = sizeof(cmd16);
- cmdp = (struct scsipi_generic *)&cmd16;
- }
-
- /* Instrumentation. */
- disk_busy(&sd->sc_dk);
-
- /*
- * Mark the disk dirty so that the cache will be
- * flushed on close.
- */
- if ((bp->b_flags & B_READ) == 0)
- sd->flags |= SDF_DIRTY;
-
- /*
- * Figure out what flags to use.
- */
- flags = XS_CTL_NOSLEEP|XS_CTL_ASYNC|XS_CTL_SIMPLE_TAG;
- if (bp->b_flags & B_READ)
- flags |= XS_CTL_DATA_IN;
- else
- flags |= XS_CTL_DATA_OUT;
-
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- xs = scsipi_make_xs_locked(periph, cmdp, cmdlen,
- (u_char *)bp->b_data, bp->b_bcount,
- SDRETRIES, SD_IO_TIMEOUT, bp, flags);
- if (__predict_false(xs == NULL)) {
- /*
- * out of memory. Keep this buffer in the queue, and
- * retry later.
- */
- callout_reset(&sd->sc_callout, hz / 2, sdrestart,
- periph);
- return;
- }
- /*
- * need to dequeue the buffer before queuing the command,
- * because cdstart may be called recursively from the
- * HBA driver
- */
-#ifdef DIAGNOSTIC
- if (bufq_get(sd->buf_queue) != bp)
- panic("sdstart(): dequeued wrong buf");
-#else
- bufq_get(sd->buf_queue);
-#endif
- error = scsipi_execute_xs(xs);
- /* with a scsipi_xfer preallocated, scsipi_command can't fail */
- KASSERT(error == 0);
- }
-}
+ mutex_exit(chan_mtx(chan));
-static void
-sdrestart(void *v)
-{
- struct scsipi_periph *periph = v;
- struct scsipi_channel *chan = periph->periph_channel;
+ dk_start(dksc, NULL);
mutex_enter(chan_mtx(chan));
- sdstart((struct scsipi_periph *)v);
- mutex_exit(chan_mtx(chan));
}
static void
sddone(struct scsipi_xfer *xs, int error)
{
struct sd_softc *sd = device_private(xs->xs_periph->periph_dev);
+ struct dk_softc *dksc = &sd->sc_dksc;
struct buf *bp = xs->bp;
if (sd->flags & SDF_FLUSHING) {
@@ -966,11 +830,7 @@ sddone(struct scsipi_xfer *xs, int error
bp->b_resid = bp->b_bcount;
}
- disk_unbusy(&sd->sc_dk, bp->b_bcount - bp->b_resid,
- (bp->b_flags & B_READ));
- rnd_add_uint32(&sd->rnd_source, bp->b_rawblkno);
-
- biodone(bp);
+ dk_done(dksc, bp);
}
}
@@ -978,6 +838,7 @@ static void
sdminphys(struct buf *bp)
{
struct sd_softc *sd = device_lookup_private(&sd_cd, SDUNIT(bp->b_dev));
+ struct dk_softc *dksc = &sd->sc_dksc;
long xmax;
/*
@@ -994,7 +855,7 @@ sdminphys(struct buf *bp)
if ((sd->flags & SDF_ANCIENT) &&
((sd->sc_periph->periph_flags &
(PERIPH_REMOVABLE | PERIPH_MEDIA_LOADED)) != PERIPH_REMOVABLE)) {
- xmax = sd->sc_dk.dk_label->d_secsize * 0xff;
+ xmax = dksc->sc_dkdev.dk_geom.dg_secsize * 0xff;
if (bp->b_bcount > xmax)
bp->b_bcount = xmax;
@@ -1003,6 +864,21 @@ sdminphys(struct buf *bp)
scsipi_adapter_minphys(sd->sc_periph->periph_channel, bp);
}
+static void
+sd_iosize(device_t dev, int *count)
+{
+ struct buf B;
+ int bmaj;
+
+ bmaj = bdevsw_lookup_major(&sd_bdevsw);
+ B.b_dev = MAKESDDEV(bmaj,device_unit(dev),RAW_PART);
+ B.b_bcount = *count;
+
+ sdminphys(&B);
+
+ *count = B.b_bcount;
+}
+
static int
sdread(dev_t dev, struct uio *uio, int ioflag)
{
@@ -1025,12 +901,11 @@ static int
sdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
struct sd_softc *sd = device_lookup_private(&sd_cd, SDUNIT(dev));
+ struct dk_softc *dksc = &sd->sc_dksc;
struct scsipi_periph *periph = sd->sc_periph;
+
int part = SDPART(dev);
int error;
-#ifdef __HAVE_OLD_DISKLABEL
- struct disklabel *newlabel = NULL;
-#endif
SC_DEBUG(sd->sc_periph, SCSIPI_DB2, ("sdioctl 0x%lx ", cmd));
@@ -1038,110 +913,17 @@ sdioctl(dev_t dev, u_long cmd, void *add
* If the device is not valid, some IOCTLs can still be
* handled on the raw partition. Check this here.
*/
- if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
- switch (cmd) {
- case DIOCKLABEL:
- case DIOCWLABEL:
- case DIOCLOCK:
- case DIOCEJECT:
- case ODIOCEJECT:
- case DIOCGCACHE:
- case DIOCSCACHE:
- case DIOCGSTRATEGY:
- case DIOCSSTRATEGY:
- case SCIOCIDENTIFY:
- case OSCIOCIDENTIFY:
- case SCIOCCOMMAND:
- case SCIOCDEBUG:
- if (part == RAW_PART)
- break;
- /* FALLTHROUGH */
- default:
- if ((periph->periph_flags & PERIPH_OPEN) == 0)
- return (ENODEV);
- else
- return (EIO);
- }
- }
-
- error = disk_ioctl(&sd->sc_dk, dev, cmd, addr, flag, l);
- if (error != EPASSTHROUGH)
- return (error);
+ if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0 &&
+ part != RAW_PART)
+ return (EIO);
- error = 0;
switch (cmd) {
- case DIOCWDINFO:
- case DIOCSDINFO:
-#ifdef __HAVE_OLD_DISKLABEL
- case ODIOCWDINFO:
- case ODIOCSDINFO:
-#endif
- {
- struct disklabel *lp;
-
- if ((flag & FWRITE) == 0)
- return (EBADF);
-
-#ifdef __HAVE_OLD_DISKLABEL
- if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
- newlabel = malloc(sizeof *newlabel, M_TEMP,
- M_WAITOK | M_ZERO);
- if (newlabel == NULL)
- return EIO;
- memcpy(newlabel, addr, sizeof (struct olddisklabel));
- lp = newlabel;
- } else
-#endif
- lp = (struct disklabel *)addr;
-
- mutex_enter(&sd->sc_dk.dk_openlock);
- sd->flags |= SDF_LABELLING;
-
- error = setdisklabel(sd->sc_dk.dk_label,
- lp, /*sd->sc_dk.dk_openmask : */0,
- sd->sc_dk.dk_cpulabel);
- if (error == 0) {
- if (cmd == DIOCWDINFO
-#ifdef __HAVE_OLD_DISKLABEL
- || cmd == ODIOCWDINFO
-#endif
- )
- error = writedisklabel(SDLABELDEV(dev),
- sdstrategy, sd->sc_dk.dk_label,
- sd->sc_dk.dk_cpulabel);
- }
-
- sd->flags &= ~SDF_LABELLING;
- mutex_exit(&sd->sc_dk.dk_openlock);
-#ifdef __HAVE_OLD_DISKLABEL
- if (newlabel != NULL)
- free(newlabel, M_TEMP);
-#endif
- return (error);
- }
-
- case DIOCKLABEL:
- if (*(int *)addr)
- periph->periph_flags |= PERIPH_KEEP_LABEL;
- else
- periph->periph_flags &= ~PERIPH_KEEP_LABEL;
- return (0);
-
- case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- return (EBADF);
- if (*(int *)addr)
- sd->flags |= SDF_WLABEL;
- else
- sd->flags &= ~SDF_WLABEL;
- return (0);
-
case DIOCLOCK:
if (periph->periph_flags & PERIPH_REMOVABLE)
return (scsipi_prevent(periph,
(*(int *)addr) ?
SPAMR_PREVENT_DT : SPAMR_ALLOW, 0));
- else
+ else
return (ENOTTY);
case DIOCEJECT:
@@ -1152,9 +934,7 @@ sdioctl(dev_t dev, u_long cmd, void *add
* Don't force eject: check that we are the only
* partition open. If so, unlock it.
*/
- if ((sd->sc_dk.dk_openmask & ~(1 << part)) == 0 &&
- sd->sc_dk.dk_bopenmask + sd->sc_dk.dk_copenmask ==
- sd->sc_dk.dk_openmask) {
+ if (DK_BUSY(dksc, part) == 0) {
error = scsipi_prevent(periph, SPAMR_ALLOW,
XS_CTL_IGNORE_NOT_READY);
if (error)
@@ -1168,24 +948,6 @@ sdioctl(dev_t dev, u_long cmd, void *add
return ((periph->periph_flags & PERIPH_REMOVABLE) == 0 ?
ENOTTY : scsipi_start(periph, SSS_STOP|SSS_LOEJ, 0));
- case DIOCGDEFLABEL:
- sdgetdefaultlabel(sd, (struct disklabel *)addr);
- return (0);
-
-#ifdef __HAVE_OLD_DISKLABEL
- case ODIOCGDEFLABEL:
- newlabel = malloc(sizeof *newlabel, M_TEMP, M_WAITOK);
- if (newlabel == NULL)
- return EIO;
- sdgetdefaultlabel(sd, newlabel);
- if (newlabel->d_npartitions <= OLDMAXPARTITIONS)
- memcpy(addr, newlabel, sizeof (struct olddisklabel));
- else
- error = ENOTTY;
- free(newlabel, M_TEMP);
- return error;
-#endif
-
case DIOCGCACHE:
return (sd_getcache(sd, (int *) addr));
@@ -1203,61 +965,19 @@ sdioctl(dev_t dev, u_long cmd, void *add
return (EBADF);
if (((sd->flags & SDF_DIRTY) != 0 || *(int *)addr != 0)) {
error = sd_flush(sd, 0);
- if (error)
+ if (error) {
sd->flags &= ~SDF_FLUSHING;
- else
- sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
- }
- return (error);
-
- case DIOCGSTRATEGY:
- {
- struct disk_strategy *dks = addr;
- int s;
-
- s = splbio();
- strlcpy(dks->dks_name, bufq_getstrategyname(sd->buf_queue),
- sizeof(dks->dks_name));
- splx(s);
- dks->dks_paramlen = 0;
-
- return 0;
- }
-
- case DIOCSSTRATEGY:
- {
- struct disk_strategy *dks = addr;
- struct bufq_state *new_bufq;
- struct bufq_state *old_bufq;
- int s;
-
- if ((flag & FWRITE) == 0) {
- return EBADF;
- }
-
- if (dks->dks_param != NULL) {
- return EINVAL;
- }
- dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
- error = bufq_alloc(&new_bufq, dks->dks_name,
- BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
- if (error) {
- return error;
+ return (error);
+ }
+ sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
}
- s = splbio();
- old_bufq = sd->buf_queue;
- bufq_move(new_bufq, old_bufq);
- sd->buf_queue = new_bufq;
- splx(s);
- bufq_free(old_bufq);
-
- return 0;
- }
+ return (0);
default:
- if (part != RAW_PART)
- return (ENOTTY);
- return (scsipi_do_ioctl(periph, dev, cmd, addr, flag, l));
+ error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
+ if (error == ENOTTY)
+ error = scsipi_do_ioctl(periph, dev, cmd, addr, flag, l);
+ return (error);
}
#ifdef DIAGNOSTIC
@@ -1266,86 +986,21 @@ sdioctl(dev_t dev, u_long cmd, void *add
}
static void
-sdgetdefaultlabel(struct sd_softc *sd, struct disklabel *lp)
-{
-
- memset(lp, 0, sizeof(struct disklabel));
-
- lp->d_secsize = sd->params.blksize;
- lp->d_ntracks = sd->params.heads;
- lp->d_nsectors = sd->params.sectors;
- lp->d_ncylinders = sd->params.cyls;
- lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+sd_label(device_t self, struct disklabel *lp)
+{
+ struct sd_softc *sd = device_private(self);
- switch (SCSIPI_BUSTYPE_TYPE(scsipi_periph_bustype(sd->sc_periph))) {
- case SCSIPI_BUSTYPE_SCSI:
- lp->d_type = DKTYPE_SCSI;
- break;
- case SCSIPI_BUSTYPE_ATAPI:
- lp->d_type = DKTYPE_ATAPI;
- break;
- }
- /*
- * XXX
- * We could probe the mode pages to figure out what kind of disc it is.
- * Is this worthwhile?
- */
strncpy(lp->d_typename, sd->name, 16);
- strncpy(lp->d_packname, "fictitious", 16);
- if (sd->params.disksize > UINT32_MAX)
- lp->d_secperunit = UINT32_MAX;
- else
- lp->d_secperunit = sd->params.disksize;
lp->d_rpm = sd->params.rot_rate;
- lp->d_interleave = 1;
- lp->d_flags = sd->sc_periph->periph_flags & PERIPH_REMOVABLE ?
- D_REMOVABLE : 0;
-
- lp->d_partitions[RAW_PART].p_offset = 0;
- lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
- lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
- lp->d_npartitions = RAW_PART + 1;
-
- lp->d_magic = DISKMAGIC;
- lp->d_magic2 = DISKMAGIC;
- lp->d_checksum = dkcksum(lp);
-}
-
-
-/*
- * Load the label information on the named device
- */
-static int
-sdgetdisklabel(struct sd_softc *sd)
-{
- struct disklabel *lp = sd->sc_dk.dk_label;
- const char *errstring;
-
- memset(sd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
-
- sdgetdefaultlabel(sd, lp);
-
- if (lp->d_secpercyl == 0) {
- lp->d_secpercyl = 100;
- /* as long as it's not 0 - readdisklabel divides by it (?) */
- }
-
- /*
- * Call the generic disklabel extraction routine
- */
- errstring = readdisklabel(MAKESDDEV(0, device_unit(sd->sc_dev),
- RAW_PART), sdstrategy, lp, sd->sc_dk.dk_cpulabel);
- if (errstring) {
- aprint_error_dev(sd->sc_dev, "%s\n", errstring);
- return EIO;
- }
- return 0;
+ if (sd->sc_periph->periph_flags & PERIPH_REMOVABLE)
+ lp->d_flags |= D_REMOVABLE;
}
static bool
sd_shutdown(device_t self, int how)
{
struct sd_softc *sd = device_private(self);
+ struct dk_softc *dksc = &sd->sc_dksc;
/*
* If the disk cache needs to be flushed, and the disk supports
@@ -1354,7 +1009,7 @@ sd_shutdown(device_t self, int how)
*/
if ((sd->flags & SDF_DIRTY) != 0) {
if (sd_flush(sd, XS_CTL_NOSLEEP|XS_CTL_POLL)) {
- aprint_error_dev(sd->sc_dev,
+ aprint_error_dev(dksc->sc_dev,
"cache synchronization failed\n");
sd->flags &= ~SDF_FLUSHING;
} else
@@ -1379,6 +1034,7 @@ sd_interpret_sense(struct scsipi_xfer *x
struct scsipi_channel *chan = periph->periph_channel;
struct scsi_sense_data *sense = &xs->sense.scsi_sense;
struct sd_softc *sd = device_private(periph->periph_dev);
+ struct dk_softc *dksc = &sd->sc_dksc;
int error, retval = EJUSTRETURN;
/*
@@ -1428,7 +1084,7 @@ sd_interpret_sense(struct scsipi_xfer *x
* Unit In The Process Of Becoming Ready.
*/
printf("%s: waiting for pack to spin up...\n",
- device_xname(sd->sc_dev));
+ dksc->sc_xname);
if (!callout_pending(&periph->periph_callout))
scsipi_periph_freeze(periph, 1);
callout_reset(&periph->periph_callout,
@@ -1436,7 +1092,7 @@ sd_interpret_sense(struct scsipi_xfer *x
retval = ERESTART;
} else if (sense->ascq == 0x02) {
printf("%s: pack is stopped, restarting...\n",
- device_xname(sd->sc_dev));
+ dksc->sc_xname);
mutex_enter(chan_mtx(chan));
periph->periph_flags |= PERIPH_RECOVERING;
mutex_exit(chan_mtx(chan));
@@ -1444,7 +1100,7 @@ sd_interpret_sense(struct scsipi_xfer *x
XS_CTL_URGENT|XS_CTL_HEAD_TAG|
XS_CTL_THAW_PERIPH|XS_CTL_FREEZE_PERIPH);
if (error) {
- aprint_error_dev(sd->sc_dev,
+ aprint_error_dev(dksc->sc_dev,
"unable to restart pack\n");
retval = error;
} else
@@ -1468,37 +1124,23 @@ static int
sdsize(dev_t dev)
{
struct sd_softc *sd;
- int part, unit, omask;
- int size;
+ struct dk_softc *dksc;
+ int unit;
unit = SDUNIT(dev);
sd = device_lookup_private(&sd_cd, unit);
if (sd == NULL)
return (-1);
+ dksc = &sd->sc_dksc;
- if (!device_is_active(sd->sc_dev))
+ if (!device_is_active(dksc->sc_dev))
return (-1);
- part = SDPART(dev);
- omask = sd->sc_dk.dk_openmask & (1 << part);
-
- if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0)
- return (-1);
- if ((sd->sc_periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
- size = -1;
- else if (sd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
- size = -1;
- else
- size = sd->sc_dk.dk_label->d_partitions[part].p_size *
- (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
- if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0)
- return (-1);
- return (size);
+ return dk_size(dksc, dev);
}
/* #define SD_DUMP_NOT_TRUSTED if you just want to watch */
static struct scsipi_xfer sx;
-static int sddoingadump;
/*
* dump all of physical memory into the partition specified, starting
@@ -1507,115 +1149,90 @@ static int sddoingadump;
static int
sddump(dev_t dev, daddr_t blkno, void *va, size_t size)
{
- struct sd_softc *sd; /* disk unit to do the I/O */
- struct disklabel *lp; /* disk's disklabel */
- int unit, part;
- int sectorsize; /* size of a disk sector */
- int nsects; /* number of sectors in partition */
- int sectoff; /* sector offset of partition */
- int totwrt; /* total number of sectors left to write */
- int nwrt; /* current number of sectors to write */
- struct scsipi_rw_10 cmd; /* write command */
- struct scsipi_xfer *xs; /* ... convenience */
+ struct sd_softc *sd;
+ struct dk_softc *dksc;
struct scsipi_periph *periph;
- struct scsipi_channel *chan;
-
- /* Check if recursive dump; if so, punt. */
- if (sddoingadump)
- return (EFAULT);
-
- /* Mark as active early. */
- sddoingadump = 1;
+ int unit;
- unit = SDUNIT(dev); /* Decompose unit & partition. */
- part = SDPART(dev);
-
- /* Check for acceptable drive number. */
- sd = device_lookup_private(&sd_cd, unit);
- if (sd == NULL)
+ unit = SDUNIT(dev);
+ if ((sd = device_lookup_private(&sd_cd, unit)) == NULL)
return (ENXIO);
+ dksc = &sd->sc_dksc;
- if (!device_is_active(sd->sc_dev))
+ if (!device_is_active(dksc->sc_dev))
return (ENODEV);
periph = sd->sc_periph;
- chan = periph->periph_channel;
/* Make sure it was initialized. */
if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
return (ENXIO);
- /* Convert to disk sectors. Request must be a multiple of size. */
- lp = sd->sc_dk.dk_label;
- sectorsize = lp->d_secsize;
- if ((size % sectorsize) != 0)
- return (EFAULT);
- totwrt = size / sectorsize;
- blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */
-
- nsects = lp->d_partitions[part].p_size;
- sectoff = lp->d_partitions[part].p_offset;
-
- /* Check transfer bounds against partition size. */
- if ((blkno < 0) || ((blkno + totwrt) > nsects))
- return (EINVAL);
+ return dk_dump(dksc, dev, blkno, va, size);
+}
+
+static int
+sd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
+{
+ struct sd_softc *sd = device_private(dev);
+ struct dk_softc *dksc = &sd->sc_dksc;
+ struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
+ struct scsipi_rw_10 cmd; /* write command */
+ struct scsipi_xfer *xs; /* ... convenience */
+ struct scsipi_periph *periph;
+ struct scsipi_channel *chan;
+ size_t sectorsize;
+
+ periph = sd->sc_periph;
+ chan = periph->periph_channel;
- /* Offset block number to start of partition. */
- blkno += sectoff;
+ sectorsize = dg->dg_secsize;
xs = &sx;
- while (totwrt > 0) {
- nwrt = totwrt; /* XXX */
#ifndef SD_DUMP_NOT_TRUSTED
- /*
- * Fill out the scsi command
- */
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = WRITE_10;
- _lto4b(blkno, cmd.addr);
- _lto2b(nwrt, cmd.length);
- /*
- * Fill out the scsipi_xfer structure
- * Note: we cannot sleep as we may be an interrupt
- * don't use scsipi_command() as it may want to wait
- * for an xs.
- */
- memset(xs, 0, sizeof(sx));
- xs->xs_control |= XS_CTL_NOSLEEP | XS_CTL_POLL |
- XS_CTL_DATA_OUT;
- xs->xs_status = 0;
- xs->xs_periph = periph;
- xs->xs_retries = SDRETRIES;
- xs->timeout = 10000; /* 10000 millisecs for a disk ! */
- xs->cmd = (struct scsipi_generic *)&cmd;
- xs->cmdlen = sizeof(cmd);
- xs->resid = nwrt * sectorsize;
- xs->error = XS_NOERROR;
- xs->bp = 0;
- xs->data = va;
- xs->datalen = nwrt * sectorsize;
- callout_init(&xs->xs_callout, 0);
-
- /*
- * Pass all this info to the scsi driver.
- */
- scsipi_adapter_request(chan, ADAPTER_REQ_RUN_XFER, xs);
- if ((xs->xs_status & XS_STS_DONE) == 0 ||
- xs->error != XS_NOERROR)
- return (EIO);
+ /*
+ * Fill out the scsi command
+ */
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = WRITE_10;
+ _lto4b(blkno, cmd.addr);
+ _lto2b(nblk, cmd.length);
+ /*
+ * Fill out the scsipi_xfer structure
+ * Note: we cannot sleep as we may be an interrupt
+ * don't use scsipi_command() as it may want to wait
+ * for an xs.
+ */
+ memset(xs, 0, sizeof(sx));
+ xs->xs_control |= XS_CTL_NOSLEEP | XS_CTL_POLL |
+ XS_CTL_DATA_OUT;
+ xs->xs_status = 0;
+ xs->xs_periph = periph;
+ xs->xs_retries = SDRETRIES;
+ xs->timeout = 10000; /* 10000 millisecs for a disk ! */
+ xs->cmd = (struct scsipi_generic *)&cmd;
+ xs->cmdlen = sizeof(cmd);
+ xs->resid = nblk * sectorsize;
+ xs->error = XS_NOERROR;
+ xs->bp = 0;
+ xs->data = va;
+ xs->datalen = nblk * sectorsize;
+ callout_init(&xs->xs_callout, 0);
+
+ /*
+ * Pass all this info to the scsi driver.
+ */
+ scsipi_adapter_request(chan, ADAPTER_REQ_RUN_XFER, xs);
+ if ((xs->xs_status & XS_STS_DONE) == 0 ||
+ xs->error != XS_NOERROR)
+ return (EIO);
#else /* SD_DUMP_NOT_TRUSTED */
- /* Let's just talk about this first... */
- printf("sd%d: dump addr 0x%x, blk %d\n", unit, va, blkno);
- delay(500 * 1000); /* half a second */
+ /* Let's just talk about this first... */
+ printf("sd%d: dump addr 0x%x, blk %d\n", unit, va, blkno);
+ delay(500 * 1000); /* half a second */
#endif /* SD_DUMP_NOT_TRUSTED */
- /* update block count */
- totwrt -= nwrt;
- blkno += nwrt;
- va = (char *)va + sectorsize * nwrt;
- }
- sddoingadump = 0;
return (0);
}
@@ -2084,6 +1701,7 @@ printf("page 5 ok\n");
static int
sd_get_parms(struct sd_softc *sd, struct disk_parms *dp, int flags)
{
+ struct dk_softc *dksc = &sd->sc_dksc;
int error;
/*
@@ -2115,7 +1733,7 @@ sd_get_parms(struct sd_softc *sd, struct
}
page0:
- printf("%s: fabricating a geometry\n", device_xname(sd->sc_dev));
+ printf("%s: fabricating a geometry\n", dksc->sc_xname);
/* Try calling driver's method for figuring out geometry. */
if (!sd->sc_periph->periph_channel->chan_adapter->adapt_getgeom ||
!(*sd->sc_periph->periph_channel->chan_adapter->adapt_getgeom)
@@ -2272,7 +1890,8 @@ sd_setcache(struct sd_softc *sd, int bit
static void
sd_set_geometry(struct sd_softc *sd)
{
- struct disk_geom *dg = &sd->sc_dk.dk_geom;
+ struct dk_softc *dksc = &sd->sc_dksc;
+ struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
memset(dg, 0, sizeof(*dg));
@@ -2282,5 +1901,5 @@ sd_set_geometry(struct sd_softc *sd)
dg->dg_ntracks = sd->params.heads;
dg->dg_ncylinders = sd->params.cyls;
- disk_set_info(sd->sc_dev, &sd->sc_dk, NULL);
+ disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
}
Index: src/sys/dev/scsipi/sdvar.h
diff -u src/sys/dev/scsipi/sdvar.h:1.37 src/sys/dev/scsipi/sdvar.h:1.38
--- src/sys/dev/scsipi/sdvar.h:1.37 Mon Aug 24 23:13:15 2015
+++ src/sys/dev/scsipi/sdvar.h Sat Dec 10 10:26:38 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: sdvar.h,v 1.37 2015/08/24 23:13:15 pooka Exp $ */
+/* $NetBSD: sdvar.h,v 1.38 2016/12/10 10:26:38 mlelstv Exp $ */
/*-
* Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
@@ -53,7 +53,7 @@
#include "opt_scsi.h"
#endif
-#include <sys/rndsource.h>
+#include <dev/dkvar.h>
#ifndef SDRETRIES
#define SDRETRIES 4
@@ -74,12 +74,9 @@ struct disk_parms {
};
struct sd_softc {
- device_t sc_dev;
- struct disk sc_dk;
+ struct dk_softc sc_dksc;
int flags;
-#define SDF_WLABEL 0x04 /* label is writable */
-#define SDF_LABELLING 0x08 /* writing label */
#define SDF_ANCIENT 0x10 /* disk is ancient; for minphys */
#define SDF_DIRTY 0x20 /* disk is dirty; needs cache flush */
#define SDF_FLUSHING 0x40 /* flushing, for sddone() */
@@ -88,12 +85,9 @@ struct sd_softc {
struct disk_parms params;
- struct bufq_state *buf_queue;
callout_t sc_callout;
u_int8_t type;
char name[16]; /* product name, for default disklabel */
-
- krndsource_t rnd_source;
};
#define SDGP_RESULT_OK 0 /* parameters obtained */