Module Name:    src
Committed By:   mlelstv
Date:           Sat May  2 08:00:09 UTC 2015

Modified Files:
        src/sys/arch/xen/include: xbdvar.h
        src/sys/arch/xen/xen: xbd_xenbus.c
        src/sys/dev: cgd.c dksubr.c dkvar.h ld.c ldvar.h
        src/sys/sys: disk.h param.h

Log Message:
Merge dk_intf and dkdriver interfaces.
Merge common disk driver functionality in ld.c with dksubr.c.
Adjust the two previous users of dk_intf (cgd and xbd) to
the changes.

bump kernel version to 7.99.14


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/xen/include/xbdvar.h
cvs rdiff -u -r1.70 -r1.71 src/sys/arch/xen/xen/xbd_xenbus.c
cvs rdiff -u -r1.97 -r1.98 src/sys/dev/cgd.c
cvs rdiff -u -r1.59 -r1.60 src/sys/dev/dksubr.c
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/dkvar.h
cvs rdiff -u -r1.82 -r1.83 src/sys/dev/ld.c
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/ldvar.h
cvs rdiff -u -r1.63 -r1.64 src/sys/sys/disk.h
cvs rdiff -u -r1.475 -r1.476 src/sys/sys/param.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/arch/xen/include/xbdvar.h
diff -u src/sys/arch/xen/include/xbdvar.h:1.16 src/sys/arch/xen/include/xbdvar.h:1.17
--- src/sys/arch/xen/include/xbdvar.h:1.16	Tue Apr 14 20:32:35 2015
+++ src/sys/arch/xen/include/xbdvar.h	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: xbdvar.h,v 1.16 2015/04/14 20:32:35 riastradh Exp $ */
+/* $NetBSD: xbdvar.h,v 1.17 2015/05/02 08:00:08 mlelstv Exp $ */
 
 /*
  *
@@ -36,7 +36,6 @@ struct xbd_softc {
 	device_t		sc_dev;		/* base device glue */
 	struct dk_softc		sc_dksc;	/* generic disk interface */
 	unsigned long		sc_xd_device;	/* cookie identifying device */
-	struct dk_intf		*sc_di;		/* pseudo-disk interface */
 	int			sc_shutdown;	/* about to be removed */
 	krndsource_t	sc_rnd_source;
 };
@@ -44,7 +43,6 @@ struct xbd_softc {
 struct xbd_attach_args {
 	const char 		*xa_device;
 	vdisk_t			*xa_xd;
-	struct dk_intf		*xa_dkintf;
 	struct sysctlnode	*xa_diskcookies;
 };
 

Index: src/sys/arch/xen/xen/xbd_xenbus.c
diff -u src/sys/arch/xen/xen/xbd_xenbus.c:1.70 src/sys/arch/xen/xen/xbd_xenbus.c:1.71
--- src/sys/arch/xen/xen/xbd_xenbus.c:1.70	Mon Apr 13 21:18:40 2015
+++ src/sys/arch/xen/xen/xbd_xenbus.c	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/*      $NetBSD: xbd_xenbus.c,v 1.70 2015/04/13 21:18:40 riastradh Exp $      */
+/*      $NetBSD: xbd_xenbus.c,v 1.71 2015/05/02 08:00:08 mlelstv Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -50,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.70 2015/04/13 21:18:40 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.71 2015/05/02 08:00:08 mlelstv Exp $");
 
 #include "opt_xen.h"
 
@@ -168,7 +168,7 @@ static bool xbd_xenbus_suspend(device_t,
 static bool xbd_xenbus_resume(device_t, const pmf_qual_t *);
 
 static int  xbd_handler(void *);
-static void xbdstart(struct dk_softc *);
+static void xbdstart(device_t);
 static void xbd_backend_changed(void *, XenbusState);
 static void xbd_connect(struct xbd_xenbus_softc *);
 
@@ -218,19 +218,12 @@ const struct cdevsw xbd_cdevsw = {
 
 extern struct cfdriver xbd_cd;
 
-/* Pseudo-disk Interface */
-static struct dk_intf dkintf_esdi = {
-        DKTYPE_ESDI,
-	"Xen Virtual ESDI",
-	xbdopen,
-	xbdclose,
-	xbdstrategy,
-	xbdstart,
-}, *di = &dkintf_esdi;
-
 static struct dkdriver xbddkdriver = {
         .d_strategy = xbdstrategy,
 	.d_minphys = xbdminphys,
+	.d_open = xbdopen,
+	.d_close = xbdclose,
+	.d_diskstart = xbdstart,
 };
 
 static int
@@ -265,8 +258,8 @@ xbd_xenbus_attach(device_t parent, devic
 	config_pending_incr(self);
 	aprint_normal(": Xen Virtual Block Device Interface\n");
 
-	dk_sc_init(&sc->sc_dksc, device_xname(self));
-	sc->sc_dksc.sc_dev = self;
+	dk_init(&sc->sc_dksc, self, DKTYPE_ESDI);
+	disk_init(&sc->sc_dksc.sc_dkdev, device_xname(self), &xbddkdriver);
 
 #ifdef XBD_DEBUG
 	printf("path: %s\n", xa->xa_xbusd->xbusd_path);
@@ -293,7 +286,6 @@ xbd_xenbus_attach(device_t parent, devic
 	sc->sc_xbusd = xa->xa_xbusd;
 	sc->sc_xbusd->xbusd_otherend_changed = xbd_backend_changed;
 
-	disk_init(&sc->sc_dksc.sc_dkdev, device_xname(self), &xbddkdriver);
 	/* initialize free requests list */
 	SLIST_INIT(&sc->sc_xbdreq_head);
 	for (i = 0; i < XBD_RING_SIZE; i++) {
@@ -380,6 +372,7 @@ xbd_xenbus_detach(device_t dev, int flag
 		/* detach disk */
 		disk_detach(&sc->sc_dksc.sc_dkdev);
 		disk_destroy(&sc->sc_dksc.sc_dkdev);
+		dk_detach(&sc->sc_dksc);
 		/* Unhook the entropy source. */
 		rnd_detach_source(&sc->sc_rnd_source);
 	}
@@ -580,13 +573,13 @@ static void xbd_backend_changed(void *ar
 		dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
 
 		bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0);
-		sc->sc_dksc.sc_flags |= DKF_INITED;
+		dk_attach(&sc->sc_dksc);
 		disk_attach(&sc->sc_dksc.sc_dkdev);
 
 		sc->sc_backend_status = BLKIF_STATE_CONNECTED;
 
 		/* try to read the disklabel */
-		dk_getdisklabel(di, &sc->sc_dksc, 0 /* XXX ? */);
+		dk_getdisklabel(&sc->sc_dksc, 0 /* XXX ? */);
 		format_bytes(buf, sizeof(buf), sc->sc_sectors * sc->sc_secsize);
 		aprint_verbose_dev(sc->sc_dksc.sc_dev,
 				"%s, %d bytes/sect x %" PRIu64 " sectors\n",
@@ -727,7 +720,7 @@ done:
 	if (sc->sc_xbdreq_wait)
 		wakeup(&sc->sc_xbdreq_wait);
 	else
-		xbdstart(&sc->sc_dksc);
+		xbdstart(sc->sc_dksc.sc_dev);
 	return 1;
 }
 
@@ -752,7 +745,7 @@ xbdopen(dev_t dev, int flags, int fmt, s
 		return EROFS;
 
 	DPRINTF(("xbdopen(0x%04x, %d)\n", dev, flags));
-	return dk_open(di, &sc->sc_dksc, dev, flags, fmt, l);
+	return dk_open(&sc->sc_dksc, dev, flags, fmt, l);
 }
 
 int
@@ -763,7 +756,7 @@ xbdclose(dev_t dev, int flags, int fmt, 
 	sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
 
 	DPRINTF(("xbdclose(%d, %d)\n", dev, flags));
-	return dk_close(di, &sc->sc_dksc, dev, flags, fmt, l);
+	return dk_close(&sc->sc_dksc, dev, flags, fmt, l);
 }
 
 void
@@ -788,7 +781,7 @@ xbdstrategy(struct buf *bp)
 		return;
 	}
 
-	dk_strategy(di, &sc->sc_dksc, bp);
+	dk_strategy(&sc->sc_dksc, bp);
 	return;
 }
 
@@ -802,7 +795,7 @@ xbdsize(dev_t dev)
 	sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
 	if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN)
 		return -1;
-	return dk_size(di, &sc->sc_dksc, dev);
+	return dk_size(&sc->sc_dksc, dev);
 }
 
 int
@@ -812,7 +805,7 @@ xbdread(dev_t dev, struct uio *uio, int 
 	    device_lookup_private(&xbd_cd, DISKUNIT(dev));
 	struct  dk_softc *dksc = &sc->sc_dksc;
 
-	if ((dksc->sc_flags & DKF_INITED) == 0)
+	if (!DK_ATTACHED(dksc))
 		return ENXIO;
 	return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio);
 }
@@ -824,7 +817,7 @@ xbdwrite(dev_t dev, struct uio *uio, int
 	    device_lookup_private(&xbd_cd, DISKUNIT(dev));
 	struct  dk_softc *dksc = &sc->sc_dksc;
 
-	if ((dksc->sc_flags & DKF_INITED) == 0)
+	if (!DK_ATTACHED(dksc))
 		return ENXIO;
 	if (__predict_false(sc->sc_info & VDISK_READONLY))
 		return EROFS;
@@ -904,7 +897,7 @@ xbdioctl(dev_t dev, u_long cmd, void *da
 		break;
 
 	default:
-		error = dk_ioctl(di, dksc, dev, cmd, data, flag, l);
+		error = dk_ioctl(dksc, dev, cmd, data, flag, l);
 		break;
 	}
 
@@ -922,13 +915,14 @@ xbddump(dev_t dev, daddr_t blkno, void *
 
 	DPRINTF(("xbddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va,
 	    (unsigned long)size));
-	return dk_dump(di, &sc->sc_dksc, dev, blkno, va, size);
+	return dk_dump(&sc->sc_dksc, dev, blkno, va, size);
 }
 
 static void
-xbdstart(struct dk_softc *dksc)
+xbdstart(device_t self)
 {
-	struct xbd_xenbus_softc *sc = (struct xbd_xenbus_softc *)dksc;
+	struct xbd_xenbus_softc *sc = device_private(self);
+	struct dk_softc *dksc = &sc->sc_dksc;
 	struct buf *bp;
 #ifdef DIAGNOSTIC
 	struct  buf *qbp; 

Index: src/sys/dev/cgd.c
diff -u src/sys/dev/cgd.c:1.97 src/sys/dev/cgd.c:1.98
--- src/sys/dev/cgd.c:1.97	Sat Apr 25 13:06:11 2015
+++ src/sys/dev/cgd.c	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: cgd.c,v 1.97 2015/04/25 13:06:11 riastradh Exp $ */
+/* $NetBSD: cgd.c,v 1.98 2015/05/02 08:00:08 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.97 2015/04/25 13:06:11 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.98 2015/05/02 08:00:08 mlelstv Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -104,7 +104,7 @@ static int cgd_destroy(device_t);
 
 /* Internal Functions */
 
-static void	cgdstart(struct dk_softc *);
+static void	cgd_start(device_t);
 static void	cgdiodone(struct buf *);
 
 static int	cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
@@ -115,21 +115,15 @@ static int	cgdinit(struct cgd_softc *, c
 static void	cgd_cipher(struct cgd_softc *, void *, void *,
 			   size_t, daddr_t, size_t, int);
 
-/* Pseudo-disk Interface */
-
-static struct dk_intf the_dkintf = {
-	DKTYPE_CGD,
-	"cgd",
-	cgdopen,
-	cgdclose,
-	cgdstrategy,
-	cgdstart,
-};
-static struct dk_intf *di = &the_dkintf;
-
 static struct dkdriver cgddkdriver = {
-	.d_strategy = cgdstrategy,
-	.d_minphys = minphys,
+        .d_minphys  = minphys,
+        .d_open = cgdopen,
+        .d_close = cgdclose,
+        .d_strategy = cgdstrategy,
+        .d_iosize = NULL,
+        .d_diskstart = cgd_start,
+        .d_dumpblocks = NULL,
+        .d_lastclose = NULL
 };
 
 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
@@ -205,11 +199,10 @@ cgd_attach(device_t parent, device_t sel
 	struct cgd_softc *sc = device_private(self);
 
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
-	dk_sc_init(&sc->sc_dksc, device_xname(self));
-	sc->sc_dksc.sc_dev = self;
+	dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
 	disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
 
-	 if (!pmf_device_register(self, NULL, NULL))
+	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "unable to register power management hooks\n");
 }
 
@@ -225,7 +218,7 @@ cgd_detach(device_t self, int flags)
 	if (DK_BUSY(dksc, pmask))
 		return EBUSY;
 
-	if ((dksc->sc_flags & DKF_INITED) != 0 &&
+	if (DK_ATTACHED(dksc) &&
 	    (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
 		return ret;
 
@@ -281,7 +274,7 @@ cgdopen(dev_t dev, int flags, int fmt, s
 
 	DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
 	GETCGD_SOFTC(cs, dev);
-	return dk_open(di, &cs->sc_dksc, dev, flags, fmt, l);
+	return dk_open(&cs->sc_dksc, dev, flags, fmt, l);
 }
 
 static int
@@ -294,10 +287,10 @@ cgdclose(dev_t dev, int flags, int fmt, 
 	DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
 	GETCGD_SOFTC(cs, dev);
 	dksc = &cs->sc_dksc;
-	if ((error =  dk_close(di, dksc, dev, flags, fmt, l)) != 0)
+	if ((error =  dk_close(dksc, dev, flags, fmt, l)) != 0)
 		return error;
 
-	if ((dksc->sc_flags & DKF_INITED) == 0) {
+	if (!DK_ATTACHED(dksc)) {
 		if ((error = cgd_destroy(cs->sc_dksc.sc_dev)) != 0) {
 			aprint_error_dev(dksc->sc_dev,
 			    "unable to detach instance\n");
@@ -330,7 +323,7 @@ cgdstrategy(struct buf *bp)
 	}
 
 	/* XXXrcd: Should we test for (cs != NULL)? */
-	dk_strategy(di, &cs->sc_dksc, bp);
+	dk_strategy(&cs->sc_dksc, bp);
 	return;
 }
 
@@ -342,7 +335,7 @@ cgdsize(dev_t dev)
 	DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
 	if (!cs)
 		return -1;
-	return dk_size(di, &cs->sc_dksc, dev);
+	return dk_size(&cs->sc_dksc, dev);
 }
 
 /*
@@ -387,9 +380,10 @@ cgd_putdata(struct dk_softc *dksc, void 
 }
 
 static void
-cgdstart(struct dk_softc *dksc)
+cgd_start(device_t dev)
 {
-	struct	cgd_softc *cs = (struct cgd_softc *)dksc;
+	struct	cgd_softc *cs = device_private(dev);
+	struct	dk_softc *dksc = &cs->sc_dksc;
 	struct	buf *bp, *nbp;
 #ifdef DIAGNOSTIC
 	struct	buf *qbp;
@@ -401,7 +395,7 @@ cgdstart(struct dk_softc *dksc)
 
 	while ((bp = bufq_peek(dksc->sc_bufq)) != NULL) {
 
-		DPRINTF_FOLLOW(("cgdstart(%p, %p)\n", dksc, bp));
+		DPRINTF_FOLLOW(("cgd_start(%p, %p)\n", dksc, bp));
 		disk_busy(&dksc->sc_dkdev);
 
 		bn = bp->b_rawblkno;
@@ -506,7 +500,7 @@ cgdiodone(struct buf *nbp)
 	disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid,
 	    (obp->b_flags & B_READ));
 	biodone(obp);
-	cgdstart(dksc);
+	cgd_start(dksc->sc_dev);
 	splx(s);
 }
 
@@ -521,7 +515,7 @@ cgdread(dev_t dev, struct uio *uio, int 
 	    (unsigned long long)dev, uio, flags));
 	GETCGD_SOFTC(cs, dev);
 	dksc = &cs->sc_dksc;
-	if ((dksc->sc_flags & DKF_INITED) == 0)
+	if (!DK_ATTACHED(dksc))
 		return ENXIO;
 	return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
 }
@@ -536,7 +530,7 @@ cgdwrite(dev_t dev, struct uio *uio, int
 	DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
 	GETCGD_SOFTC(cs, dev);
 	dksc = &cs->sc_dksc;
-	if ((dksc->sc_flags & DKF_INITED) == 0)
+	if (!DK_ATTACHED(dksc))
 		return ENXIO;
 	return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
 }
@@ -568,7 +562,7 @@ cgdioctl(dev_t dev, u_long cmd, void *da
 
 	switch (cmd) {
 	case CGDIOCSET:
-		if (dksc->sc_flags & DKF_INITED)
+		if (DK_ATTACHED(dksc))
 			return EBUSY;
 		return cgd_ioctl_set(cs, data, l);
 	case CGDIOCCLR:
@@ -588,7 +582,7 @@ cgdioctl(dev_t dev, u_long cmd, void *da
 		 */
 		return VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
 	default:
-		return dk_ioctl(di, dksc, dev, cmd, data, flag, l);
+		return dk_ioctl(dksc, dev, cmd, data, flag, l);
 	case CGDIOCGET:
 		KASSERT(0);
 		return EINVAL;
@@ -603,7 +597,7 @@ cgddump(dev_t dev, daddr_t blkno, void *
 	DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
 	    dev, blkno, va, (unsigned long)size));
 	GETCGD_SOFTC(cs, dev);
-	return dk_dump(di, &cs->sc_dksc, dev, blkno, va, size);
+	return dk_dump(&cs->sc_dksc, dev, blkno, va, size);
 }
 
 /*
@@ -717,15 +711,14 @@ cgd_ioctl_set(struct cgd_softc *cs, void
 	cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
 	cs->sc_data_used = 0;
 
-	dksc->sc_flags |= DKF_INITED;
-
-	disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
-
 	/* Attach the disk. */
+	dk_attach(dksc);
 	disk_attach(&dksc->sc_dkdev);
 
+	disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
+
 	/* Try and read the disklabel. */
-	dk_getdisklabel(di, dksc, 0 /* XXX ? (cause of PR 41704) */);
+	dk_getdisklabel(dksc, 0 /* XXX ? (cause of PR 41704) */);
 
 	/* Discover wedges on this disk. */
 	dkwedge_discover(&dksc->sc_dkdev);
@@ -745,7 +738,7 @@ cgd_ioctl_clr(struct cgd_softc *cs, stru
 	int	s;
 	struct	dk_softc *dksc = &cs->sc_dksc;
 
-	if ((dksc->sc_flags & DKF_INITED) == 0)
+	if (!DK_ATTACHED(dksc))
 		return ENXIO;
 
 	/* Delete all of our wedges. */
@@ -762,7 +755,7 @@ cgd_ioctl_clr(struct cgd_softc *cs, stru
 	free(cs->sc_tpath, M_DEVBUF);
 	free(cs->sc_data, M_DEVBUF);
 	cs->sc_data_used = 0;
-	dksc->sc_flags &= ~DKF_INITED;
+	dk_detach(dksc);
 	disk_detach(&dksc->sc_dkdev);
 
 	return 0;
@@ -789,7 +782,7 @@ cgd_ioctl_get(dev_t dev, void *data, str
 		return EINVAL;	/* XXX: should this be ENXIO? */
 
 	cs = device_lookup_private(&cgd_cd, unit);
-	if (cs == NULL || (dksc->sc_flags & DKF_INITED) == 0) {
+	if (cs == NULL || !DK_ATTACHED(dksc)) {
 		cgu->cgu_dev = 0;
 		cgu->cgu_alg[0] = '\0';
 		cgu->cgu_blocksize = 0;

Index: src/sys/dev/dksubr.c
diff -u src/sys/dev/dksubr.c:1.59 src/sys/dev/dksubr.c:1.60
--- src/sys/dev/dksubr.c:1.59	Fri May  1 12:30:28 2015
+++ src/sys/dev/dksubr.c	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dksubr.c,v 1.59 2015/05/01 12:30:28 mlelstv Exp $ */
+/* $NetBSD: dksubr.c,v 1.60 2015/05/02 08:00:08 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 1999, 2002, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.59 2015/05/01 12:30:28 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.60 2015/05/02 08:00:08 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1
 #include <sys/fcntl.h>
 #include <sys/namei.h>
 #include <sys/module.h>
+#include <sys/syslog.h>
 
 #include <dev/dkvar.h>
 #include <miscfs/specfs/specdev.h> /* for v_rdev */
@@ -71,20 +72,35 @@ static int dk_subr_modcmd(modcmd_t, void
 #define DKLABELDEV(dev)	\
 	(MAKEDISKDEV(major((dev)), DISKUNIT((dev)), RAW_PART))
 
-static void	dk_makedisklabel(struct dk_intf *, struct dk_softc *);
+static void	dk_makedisklabel(struct dk_softc *);
 
 void
-dk_sc_init(struct dk_softc *dksc, const char *xname)
+dk_init(struct dk_softc *dksc, device_t dev, int dtype)
 {
 
 	memset(dksc, 0x0, sizeof(*dksc));
-	strncpy(dksc->sc_xname, xname, DK_XNAME_SIZE);
+	dksc->sc_dtype = dtype;
+	dksc->sc_dev = dev;
+
+	strncpy(dksc->sc_xname, device_xname(dev), DK_XNAME_SIZE);
 	dksc->sc_dkdev.dk_name = dksc->sc_xname;
 }
 
+void
+dk_attach(struct dk_softc *dksc)
+{
+	dksc->sc_flags |= DKF_INITED | DKF_WARNLABEL | DKF_LABELSANITY;
+}
+
+void
+dk_detach(struct dk_softc *dksc)
+{
+	dksc->sc_flags &= ~DKF_INITED;
+}
+
 /* ARGSUSED */
 int
-dk_open(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
+dk_open(struct dk_softc *dksc, dev_t dev,
     int flags, int fmt, struct lwp *l)
 {
 	struct	disklabel *lp = dksc->sc_dkdev.dk_label;
@@ -94,7 +110,7 @@ dk_open(struct dk_intf *di, struct dk_so
 	struct disk *dk = &dksc->sc_dkdev;
 
 	DPRINTF_FOLLOW(("dk_open(%s, %p, 0x%"PRIx64", 0x%x)\n",
-	    di->di_dkname, dksc, dev, flags));
+	    dksc->sc_xname, dksc, dev, flags));
 
 	mutex_enter(&dk->dk_openlock);
 	part = DISKPART(dev);
@@ -115,17 +131,17 @@ dk_open(struct dk_intf *di, struct dk_so
 	 * update the in-core disklabel.
 	 */
 	if ((dksc->sc_flags & DKF_INITED)) {
-		if (dk->dk_openmask == 0) {
-			dk_getdisklabel(di, dksc, dev);
+		if ((dksc->sc_flags & DKF_VLABEL) == 0) {
+			dksc->sc_flags |= DKF_VLABEL;
+			dk_getdisklabel(dksc, dev);
 		}
-		/* XXX re-discover wedges? */
 	}
 
 	/* Fail if we can't find the partition. */
-	if ((part != RAW_PART) &&
-	    (((dksc->sc_flags & DKF_INITED) == 0) ||
-	    ((part >= lp->d_npartitions) ||
-	    (lp->d_partitions[part].p_fstype == FS_UNUSED)))) {
+	if (part != RAW_PART &&
+	    ((dksc->sc_flags & DKF_VLABEL) == 0 ||
+	     part >= lp->d_npartitions ||
+	     lp->d_partitions[part].p_fstype == FS_UNUSED)) {
 		ret = ENXIO;
 		goto done;
 	}
@@ -149,15 +165,16 @@ done:
 
 /* ARGSUSED */
 int
-dk_close(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
+dk_close(struct dk_softc *dksc, dev_t dev,
     int flags, int fmt, struct lwp *l)
 {
+	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
 	int	part = DISKPART(dev);
 	int	pmask = 1 << part;
 	struct disk *dk = &dksc->sc_dkdev;
 
 	DPRINTF_FOLLOW(("dk_close(%s, %p, 0x%"PRIx64", 0x%x)\n",
-	    di->di_dkname, dksc, dev, flags));
+	    dksc->sc_xname, dksc, dev, flags));
 
 	mutex_enter(&dk->dk_openlock);
 
@@ -171,13 +188,22 @@ dk_close(struct dk_intf *di, struct dk_s
 	}
 	dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
 
+	if (dk->dk_openmask == 0) {
+		if (dkd->d_lastclose != NULL)
+			(*dkd->d_lastclose)(dksc->sc_dev);
+	}
+
+	if ((dksc->sc_flags & DKF_KLABEL) == 0)
+		dksc->sc_flags &= ~DKF_VLABEL;
+
 	mutex_exit(&dk->dk_openlock);
 	return 0;
 }
 
 void
-dk_strategy(struct dk_intf *di, struct dk_softc *dksc, struct buf *bp)
+dk_strategy(struct dk_softc *dksc, struct buf *bp)
 {
+	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
 	int	s, part;
 	int	wlabel;
 	daddr_t	blkno;
@@ -187,7 +213,7 @@ dk_strategy(struct dk_intf *di, struct d
 	unsigned secsize;
 
 	DPRINTF_FOLLOW(("dk_strategy(%s, %p, %p)\n",
-	    di->di_dkname, dksc, bp));
+	    dksc->sc_xname, dksc, bp));
 
 	if (!(dksc->sc_flags & DKF_INITED)) {
 		DPRINTF_FOLLOW(("dk_strategy: not inited\n"));
@@ -245,14 +271,33 @@ dk_strategy(struct dk_intf *di, struct d
 	 */
 	s = splbio();
 	bufq_put(dksc->sc_bufq, bp);
-	di->di_diskstart(dksc);
+	dkd->d_diskstart(dksc->sc_dev);
 	splx(s);
 	return;
 }
 
+void
+dk_done(struct dk_softc *dksc, struct buf *bp)
+{
+	struct disk *dk = &dksc->sc_dkdev;
+
+	if (bp->b_error != 0) {
+		diskerr(bp, dksc->sc_xname, "error", LOG_PRINTF, 0,
+			dk->dk_label);
+		printf("\n");
+	}
+
+	disk_unbusy(dk, bp->b_bcount - bp->b_resid, (bp->b_flags & B_READ));
+#ifdef notyet
+	rnd_add_uint(&dksc->sc_rnd_source, bp->b_rawblkno);
+#endif
+	biodone(bp);
+}
+
 int
-dk_size(struct dk_intf *di, struct dk_softc *dksc, dev_t dev)
+dk_size(struct dk_softc *dksc, dev_t dev)
 {
+	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
 	struct	disklabel *lp;
 	int	is_open;
 	int	part;
@@ -264,7 +309,7 @@ dk_size(struct dk_intf *di, struct dk_so
 	part = DISKPART(dev);
 	is_open = dksc->sc_dkdev.dk_openmask & (1 << part);
 
-	if (!is_open && di->di_open(dev, 0, S_IFBLK, curlwp))
+	if (!is_open && dkd->d_open(dev, 0, S_IFBLK, curlwp))
 		return -1;
 
 	lp = dksc->sc_dkdev.dk_label;
@@ -274,16 +319,17 @@ dk_size(struct dk_intf *di, struct dk_so
 		size = lp->d_partitions[part].p_size *
 		    (lp->d_secsize / DEV_BSIZE);
 
-	if (!is_open && di->di_close(dev, 0, S_IFBLK, curlwp))
+	if (!is_open && dkd->d_close(dev, 0, S_IFBLK, curlwp))
 		return -1;
 
 	return size;
 }
 
 int
-dk_ioctl(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
+dk_ioctl(struct dk_softc *dksc, dev_t dev,
 	    u_long cmd, void *data, int flag, struct lwp *l)
 {
+	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
 	struct	disklabel *lp;
 	struct	disk *dk = &dksc->sc_dkdev;
 #ifdef __HAVE_OLD_DISKLABEL
@@ -292,7 +338,7 @@ dk_ioctl(struct dk_intf *di, struct dk_s
 	int	error;
 
 	DPRINTF_FOLLOW(("dk_ioctl(%s, %p, 0x%"PRIx64", 0x%lx)\n",
-	    di->di_dkname, dksc, dev, cmd));
+	    dksc->sc_xname, dksc, dev, cmd));
 
 	/* ensure that the pseudo disk is open for writes for these commands */
 	switch (cmd) {
@@ -315,6 +361,7 @@ dk_ioctl(struct dk_intf *di, struct dk_s
 	case DIOCSDINFO:
 	case DIOCWDINFO:
 	case DIOCGPART:
+	case DIOCKLABEL:
 	case DIOCWLABEL:
 	case DIOCGDEFLABEL:
 	case DIOCAWEDGE:
@@ -366,7 +413,7 @@ dk_ioctl(struct dk_intf *di, struct dk_s
 #endif
 			   )
 				error = writedisklabel(DKLABELDEV(dev),
-				    di->di_strategy, dksc->sc_dkdev.dk_label,
+				    dkd->d_strategy, dksc->sc_dkdev.dk_label,
 				    dksc->sc_dkdev.dk_cpulabel);
 		}
 
@@ -374,6 +421,15 @@ dk_ioctl(struct dk_intf *di, struct dk_s
 		mutex_exit(&dk->dk_openlock);
 		break;
 
+	case DIOCKLABEL:
+		if ((flag & FWRITE) == 0)
+			return (EBADF);
+		if (*(int *)data != 0)
+			dksc->sc_flags |= DKF_KLABEL;
+		else
+			dksc->sc_flags &= ~DKF_KLABEL;
+		break;
+
 	case DIOCWLABEL:
 		if (*(int *)data != 0)
 			dksc->sc_flags |= DKF_WLABEL;
@@ -382,12 +438,12 @@ dk_ioctl(struct dk_intf *di, struct dk_s
 		break;
 
 	case DIOCGDEFLABEL:
-		dk_getdefaultlabel(di, dksc, (struct disklabel *)data);
+		dk_getdefaultlabel(dksc, (struct disklabel *)data);
 		break;
 
 #ifdef __HAVE_OLD_DISKLABEL
 	case ODIOCGDEFLABEL:
-		dk_getdefaultlabel(di, dksc, &newlabel);
+		dk_getdefaultlabel(dksc, &newlabel);
 		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
 			return ENOTTY;
 		memcpy(data, &newlabel, sizeof (struct olddisklabel));
@@ -449,7 +505,6 @@ dk_ioctl(struct dk_intf *di, struct dk_s
  * This requires substantially more framework than {s,w}ddump, and hence
  * is probably much more fragile.
  *
- * XXX: we currently do not implement this.
  */
 
 #define DKF_READYFORDUMP	(DKF_INITED|DKF_TAKEDUMP)
@@ -458,9 +513,14 @@ static volatile int	dk_dumping = 0;
 
 /* ARGSUSED */
 int
-dk_dump(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
-    daddr_t blkno, void *va, size_t size)
+dk_dump(struct dk_softc *dksc, dev_t dev,
+    daddr_t blkno, void *vav, size_t size)
 {
+	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
+	char *va = vav;
+	struct disklabel *lp;
+	int part, towrt, nsects, sectoff, maxblkcnt, nblk;
+	int maxxfer, rv = 0;
 
 	/*
 	 * ensure that we consider this device to be safe for dumping,
@@ -474,17 +534,53 @@ dk_dump(struct dk_intf *di, struct dk_so
 		return EFAULT;
 	dk_dumping = 1;
 
-	/* XXX: unimplemented */
+	if (dkd->d_dumpblocks == NULL)
+		return ENXIO;
+
+	/* device specific max transfer size */
+	maxxfer = MAXPHYS;
+	if (dkd->d_iosize != NULL)
+		(*dkd->d_iosize)(dksc->sc_dev, &maxxfer);
+
+	/* Convert to disk sectors.  Request must be a multiple of size. */
+	part = DISKPART(dev);
+	lp = dksc->sc_dkdev.dk_label;
+	if ((size % lp->d_secsize) != 0)
+		return (EFAULT);
+	towrt = size / lp->d_secsize;
+	blkno = dbtob(blkno) / lp->d_secsize;   /* blkno in secsize 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 + towrt) > nsects))
+		return (EINVAL);
+
+	/* Offset block number to start of partition. */
+	blkno += sectoff;
+
+	/* Start dumping and return when done. */
+	maxblkcnt = howmany(maxxfer, lp->d_secsize);
+	while (towrt > 0) {
+		nblk = min(maxblkcnt, towrt);
+
+		if ((rv = (*dkd->d_dumpblocks)(dksc->sc_dev, va, blkno, nblk)) != 0)
+			return (rv);
+
+		towrt -= nblk;
+		blkno += nblk;
+		va += nblk * lp->d_secsize;
+	}
 
 	dk_dumping = 0;
 
-	/* XXX: actually for now, we are going to leave this alone */
-	return ENXIO;
+	return 0;
 }
 
 /* ARGSUSED */
 void
-dk_getdefaultlabel(struct dk_intf *di, struct dk_softc *dksc,
+dk_getdefaultlabel(struct dk_softc *dksc,
 		      struct disklabel *lp)
 {
 	struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
@@ -501,8 +597,8 @@ dk_getdefaultlabel(struct dk_intf *di, s
 	lp->d_ncylinders = dg->dg_ncylinders;
 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
 
-	strncpy(lp->d_typename, di->di_dkname, sizeof(lp->d_typename));
-	lp->d_type = di->di_dtype;
+	strncpy(lp->d_typename, dksc->sc_xname, sizeof(lp->d_typename));
+	lp->d_type = dksc->sc_dtype;
 	strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
 	lp->d_rpm = 3600;
 	lp->d_interleave = 1;
@@ -520,21 +616,22 @@ dk_getdefaultlabel(struct dk_intf *di, s
 
 /* ARGSUSED */
 void
-dk_getdisklabel(struct dk_intf *di, struct dk_softc *dksc, dev_t dev)
+dk_getdisklabel(struct dk_softc *dksc, dev_t dev)
 {
+	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
 	struct	 disklabel *lp = dksc->sc_dkdev.dk_label;
 	struct	 cpu_disklabel *clp = dksc->sc_dkdev.dk_cpulabel;
-	struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
+	struct   disk_geom *dg = &dksc->sc_dkdev.dk_geom;
 	struct	 partition *pp;
 	int	 i;
 	const char	*errstring;
 
 	memset(clp, 0x0, sizeof(*clp));
-	dk_getdefaultlabel(di, dksc, lp);
-	errstring = readdisklabel(DKLABELDEV(dev), di->di_strategy,
+	dk_getdefaultlabel(dksc, lp);
+	errstring = readdisklabel(DKLABELDEV(dev), dkd->d_strategy,
 	    dksc->sc_dkdev.dk_label, dksc->sc_dkdev.dk_cpulabel);
 	if (errstring) {
-		dk_makedisklabel(di, dksc);
+		dk_makedisklabel(dksc);
 		if (dksc->sc_flags & DKF_WARNLABEL)
 			printf("%s: %s\n", dksc->sc_xname, errstring);
 		return;
@@ -549,7 +646,7 @@ dk_getdisklabel(struct dk_intf *di, stru
 		lp->d_secperunit > dg->dg_secperunit)
 		printf("WARNING: %s: total sector size in disklabel (%ju) "
 		    "!= the size of %s (%ju)\n", dksc->sc_xname,
-		    (uintmax_t)lp->d_secperunit, di->di_dkname,
+		    (uintmax_t)lp->d_secperunit, dksc->sc_xname,
 		    (uintmax_t)dg->dg_secperunit);
 
 	for (i=0; i < lp->d_npartitions; i++) {
@@ -557,14 +654,14 @@ dk_getdisklabel(struct dk_intf *di, stru
 		if (pp->p_offset + pp->p_size > dg->dg_secperunit)
 			printf("WARNING: %s: end of partition `%c' exceeds "
 			    "the size of %s (%ju)\n", dksc->sc_xname,
-			    'a' + i, di->di_dkname,
+			    'a' + i, dksc->sc_xname,
 			    (uintmax_t)dg->dg_secperunit);
 	}
 }
 
 /* ARGSUSED */
 static void
-dk_makedisklabel(struct dk_intf *di, struct dk_softc *dksc)
+dk_makedisklabel(struct dk_softc *dksc)
 {
 	struct	disklabel *lp = dksc->sc_dkdev.dk_label;
 

Index: src/sys/dev/dkvar.h
diff -u src/sys/dev/dkvar.h:1.19 src/sys/dev/dkvar.h:1.20
--- src/sys/dev/dkvar.h:1.19	Sun May 25 19:23:49 2014
+++ src/sys/dev/dkvar.h	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dkvar.h,v 1.19 2014/05/25 19:23:49 bouyer Exp $ */
+/* $NetBSD: dkvar.h,v 1.20 2015/05/02 08:00:08 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -31,7 +31,6 @@
 
 struct pathbuf; /* from namei.h */
 
-
 /* literally this is not a softc, but is intended to be included in
  * the pseudo-disk's softc and passed to calls in dksubr.c.  It
  * should include the common elements of the pseudo-disk's softc.
@@ -46,6 +45,7 @@ struct dk_softc {
 	char			 sc_xname[DK_XNAME_SIZE]; /* external name */
 	struct disk		 sc_dkdev;	/* generic disk info */
 	struct bufq_state	*sc_bufq;	/* buffer queue */
+	int			 sc_dtype;	/* disk type */
 };
 
 /* sc_flags:
@@ -59,23 +59,13 @@ struct dk_softc {
 #define DKF_WARNLABEL	0x00080000 /* warn if disklabel not present */
 #define DKF_LABELSANITY	0x00100000 /* warn if disklabel not sane */
 #define DKF_TAKEDUMP	0x00200000 /* allow dumping */
+#define DKF_KLABEL      0x00400000 /* keep label on close */
+#define DKF_VLABEL      0x00800000 /* label is valid */
 
 /* Mask of flags that dksubr.c understands, other flags are fair game */
 #define DK_FLAGMASK	0xffff0000
 
-/*
- * This defines the interface to the routines in dksubr.c.  This
- * should be a single static structure per pseudo-disk driver.
- * We only define the functions that we currently need.
- */
-struct dk_intf {
-	int	  di_dtype;			/* disk type */
-	const char *di_dkname;			/* disk type name */
-	int	(*di_open)(dev_t, int, int, struct lwp *);
-	int	(*di_close)(dev_t, int, int, struct lwp *);
-	void	(*di_strategy)(struct buf *);
-	void	(*di_diskstart)(struct dk_softc *);
-};
+#define DK_ATTACHED(_dksc) ((_dksc)->sc_flags & DKF_INITED)
 
 #define DK_BUSY(_dksc, _pmask)				\
 	(((_dksc)->sc_dkdev.dk_openmask & ~(_pmask)) ||	\
@@ -86,20 +76,22 @@ struct dk_intf {
  * Functions that are exported to the pseudo disk implementations:
  */
 
-void	dk_sc_init(struct dk_softc *, const char *);
+void	dk_init(struct dk_softc *, device_t, int);
+void	dk_attach(struct dk_softc *);
+void	dk_detach(struct dk_softc *);
 
-int	dk_open(struct dk_intf *, struct dk_softc *, dev_t,
+int	dk_open(struct dk_softc *, dev_t,
 		int, int, struct lwp *);
-int	dk_close(struct dk_intf *, struct dk_softc *, dev_t,
+int	dk_close(struct dk_softc *, dev_t,
 		 int, int, struct lwp *);
-void	dk_strategy(struct dk_intf *, struct dk_softc *, struct buf *);
-int	dk_size(struct dk_intf *, struct dk_softc *, dev_t);
-int	dk_ioctl(struct dk_intf *, struct dk_softc *, dev_t,
+void	dk_strategy(struct dk_softc *, struct buf *);
+void	dk_done(struct dk_softc *, struct buf *);
+int	dk_size(struct dk_softc *, dev_t);
+int	dk_ioctl(struct dk_softc *, dev_t,
 		 u_long, void *, int, struct lwp *);
-int	dk_dump(struct dk_intf *, struct dk_softc *, dev_t,
+int	dk_dump(struct dk_softc *, dev_t,
 		daddr_t, void *, size_t);
-void	dk_getdisklabel(struct dk_intf *, struct dk_softc *, dev_t);
-void	dk_getdefaultlabel(struct dk_intf *, struct dk_softc *,
-			   struct disklabel *);
+void	dk_getdisklabel(struct dk_softc *, dev_t);
+void	dk_getdefaultlabel(struct dk_softc *, struct disklabel *);
 
 int	dk_lookup(struct pathbuf *, struct lwp *, struct vnode **);

Index: src/sys/dev/ld.c
diff -u src/sys/dev/ld.c:1.82 src/sys/dev/ld.c:1.83
--- src/sys/dev/ld.c:1.82	Mon Apr 13 16:33:23 2015
+++ src/sys/dev/ld.c	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ld.c,v 1.82 2015/04/13 16:33:23 riastradh Exp $	*/
+/*	$NetBSD: ld.c,v 1.83 2015/05/02 08:00:08 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.82 2015/04/13 16:33:23 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.83 2015/05/02 08:00:08 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -60,15 +60,16 @@ __KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.82 
 
 #include <prop/proplib.h>
 
-static void	ldgetdefaultlabel(struct ld_softc *, struct disklabel *);
-static void	ldgetdisklabel(struct ld_softc *);
 static void	ldminphys(struct buf *bp);
 static bool	ld_suspend(device_t, const pmf_qual_t *);
 static bool	ld_shutdown(device_t, int);
-static void	ldstart(struct ld_softc *, struct buf *);
+static void	ld_start(device_t);
+static void	ld_iosize(device_t, int *);
+static int	ld_dumpblocks(device_t, void *, daddr_t, int);
+static void	ld_fake_geometry(struct ld_softc *);
 static void	ld_set_geometry(struct ld_softc *);
 static void	ld_config_interrupts (device_t);
-static int	ldlastclose(device_t);
+static int	ld_lastclose(device_t);
 
 extern struct	cfdriver ld_cd;
 
@@ -107,72 +108,59 @@ const struct cdevsw ld_cdevsw = {
 	.d_flag = D_DISK
 };
 
-static struct	dkdriver lddkdriver = { ldstrategy, ldminphys };
+static struct	dkdriver lddkdriver = {
+	.d_open = ldopen,
+	.d_close = ldclose,
+	.d_strategy = ldstrategy,
+	.d_iosize = ld_iosize,
+	.d_minphys  = ldminphys,
+	.d_diskstart = ld_start,
+	.d_dumpblocks = ld_dumpblocks,
+	.d_lastclose = ld_lastclose
+};
 
 void
 ldattach(struct ld_softc *sc)
 {
-	char tbuf[9];
+	device_t self = sc->sc_dv;
+	struct dk_softc *dksc = &sc->sc_dksc;
 
 	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM);
 
 	if ((sc->sc_flags & LDF_ENABLED) == 0) {
-		aprint_normal_dev(sc->sc_dv, "disabled\n");
 		return;
 	}
 
-	/* Initialise and attach the disk structure. */
-	disk_init(&sc->sc_dk, device_xname(sc->sc_dv), &lddkdriver);
-	disk_attach(&sc->sc_dk);
+	/* Initialise dk and disk structure. */
+	dk_init(dksc, self, DKTYPE_LD);
+	disk_init(&dksc->sc_dkdev, dksc->sc_xname, &lddkdriver);
+
+	/* Attach the device into the rnd source list. */
+	rnd_attach_source(&sc->sc_rnd_source, dksc->sc_xname,
+	    RND_TYPE_DISK, RND_FLAG_DEFAULT);
 
 	if (sc->sc_maxxfer > MAXPHYS)
 		sc->sc_maxxfer = MAXPHYS;
 
 	/* Build synthetic geometry if necessary. */
 	if (sc->sc_nheads == 0 || sc->sc_nsectors == 0 ||
-	    sc->sc_ncylinders == 0) {
-		uint64_t ncyl;
-
-		if (sc->sc_secperunit <= 528 * 2048)		/* 528MB */
-			sc->sc_nheads = 16;
-		else if (sc->sc_secperunit <= 1024 * 2048)	/* 1GB */
-			sc->sc_nheads = 32;
-		else if (sc->sc_secperunit <= 21504 * 2048)	/* 21GB */
-			sc->sc_nheads = 64;
-		else if (sc->sc_secperunit <= 43008 * 2048)	/* 42GB */
-			sc->sc_nheads = 128;
-		else
-			sc->sc_nheads = 255;
+	    sc->sc_ncylinders == 0)
+	    ld_fake_geometry(sc);
 
-		sc->sc_nsectors = 63;
-		sc->sc_ncylinders = INT_MAX;
-		ncyl = sc->sc_secperunit /
-		    (sc->sc_nheads * sc->sc_nsectors);
-		if (ncyl < INT_MAX)
-			sc->sc_ncylinders = (int)ncyl;
-	}
-
-	format_bytes(tbuf, sizeof(tbuf), sc->sc_secperunit *
-	    sc->sc_secsize);
-	aprint_normal_dev(sc->sc_dv, "%s, %d cyl, %d head, %d sec, "
-	    "%d bytes/sect x %"PRIu64" sectors\n",
-	    tbuf, sc->sc_ncylinders, sc->sc_nheads,
-	    sc->sc_nsectors, sc->sc_secsize, sc->sc_secperunit);
 	sc->sc_disksize512 = sc->sc_secperunit * sc->sc_secsize / DEV_BSIZE;
 
+	/* Attach dk and disk subsystems */
+	dk_attach(dksc);
+	disk_attach(&dksc->sc_dkdev);
 	ld_set_geometry(sc);
 
-	/* Attach the device into the rnd source list. */
-	rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dv),
-	    RND_TYPE_DISK, RND_FLAG_DEFAULT);
+	bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
 
 	/* Register with PMF */
-	if (!pmf_device_register1(sc->sc_dv, ld_suspend, NULL, ld_shutdown))
-		aprint_error_dev(sc->sc_dv,
+	if (!pmf_device_register1(dksc->sc_dev, ld_suspend, NULL, ld_shutdown))
+		aprint_error_dev(dksc->sc_dev,
 		    "couldn't establish power handler\n");
 
-	bufq_alloc(&sc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
-
 	/* Discover wedges on this disk. */
 	config_interrupts(sc->sc_dv, ld_config_interrupts);
 }
@@ -192,19 +180,22 @@ ldadjqparam(struct ld_softc *sc, int xma
 int
 ldbegindetach(struct ld_softc *sc, int flags)
 {
+	struct dk_softc *dksc = &sc->sc_dksc;
 	int s, rv = 0;
 
 	if ((sc->sc_flags & LDF_ENABLED) == 0)
 		return (0);
 
-	rv = disk_begindetach(&sc->sc_dk, ldlastclose, sc->sc_dv, flags);
+	rv = disk_begindetach(&dksc->sc_dkdev, ld_lastclose, dksc->sc_dev, flags);
 
 	if (rv != 0)
 		return rv;
 
 	s = splbio();
 	sc->sc_maxqueuecnt = 0;
-	sc->sc_flags |= LDF_DETACH;
+
+	dk_detach(dksc);
+
 	while (sc->sc_queuecnt > 0) {
 		sc->sc_flags |= LDF_DRAIN;
 		rv = tsleep(&sc->sc_queuecnt, PRIBIO, "lddrn", 0);
@@ -219,6 +210,7 @@ ldbegindetach(struct ld_softc *sc, int f
 void
 ldenddetach(struct ld_softc *sc)
 {
+	struct dk_softc *dksc = &sc->sc_dksc;
 	int s, bmaj, cmaj, i, mn;
 
 	if ((sc->sc_flags & LDF_ENABLED) == 0)
@@ -227,7 +219,7 @@ ldenddetach(struct ld_softc *sc)
 	/* Wait for commands queued with the hardware to complete. */
 	if (sc->sc_queuecnt != 0)
 		if (tsleep(&sc->sc_queuecnt, PRIBIO, "lddtch", 30 * hz))
-			printf("%s: not drained\n", device_xname(sc->sc_dv));
+			printf("%s: not drained\n", dksc->sc_xname);
 
 	/* Locate the major numbers. */
 	bmaj = bdevsw_lookup_major(&ld_bdevsw);
@@ -235,30 +227,30 @@ ldenddetach(struct ld_softc *sc)
 
 	/* Kill off any queued buffers. */
 	s = splbio();
-	bufq_drain(sc->sc_bufq);
+	bufq_drain(dksc->sc_bufq);
 	splx(s);
 
-	bufq_free(sc->sc_bufq);
+	bufq_free(dksc->sc_bufq);
 
 	/* Nuke the vnodes for any open instances. */
 	for (i = 0; i < MAXPARTITIONS; i++) {
-		mn = DISKMINOR(device_unit(sc->sc_dv), i);
+		mn = DISKMINOR(device_unit(dksc->sc_dev), i);
 		vdevgone(bmaj, mn, mn, VBLK);
 		vdevgone(cmaj, mn, mn, VCHR);
 	}
 
 	/* Delete all of our wedges. */
-	dkwedge_delall(&sc->sc_dk);
+	dkwedge_delall(&dksc->sc_dkdev);
 
 	/* Detach from the disk list. */
-	disk_detach(&sc->sc_dk);
-	disk_destroy(&sc->sc_dk);
+	disk_detach(&dksc->sc_dkdev);
+	disk_destroy(&dksc->sc_dkdev);
 
 	/* Unhook the entropy source. */
 	rnd_detach_source(&sc->sc_rnd_source);
 
 	/* Deregister with PMF */
-	pmf_device_deregister(sc->sc_dv);
+	pmf_device_deregister(dksc->sc_dev);
 
 	/*
 	 * XXX We can't really flush the cache here, beceause the
@@ -269,7 +261,7 @@ ldenddetach(struct ld_softc *sc)
 	/* Flush the device's cache. */
 	if (sc->sc_flush != NULL)
 		if ((*sc->sc_flush)(sc, 0) != 0)
-			aprint_error_dev(sc->sc_dv, "unable to flush cache\n");
+			aprint_error_dev(dksc->sc_dev, "unable to flush cache\n");
 #endif
 	mutex_destroy(&sc->sc_mutex);
 }
@@ -286,9 +278,10 @@ static bool
 ld_shutdown(device_t dev, int flags)
 {
 	struct ld_softc *sc = device_private(dev);
+	struct dk_softc *dksc = &sc->sc_dksc;
 
 	if (sc->sc_flush != NULL && (*sc->sc_flush)(sc, LDFL_POLL) != 0) {
-		printf("%s: unable to flush cache\n", device_xname(dev));
+		printf("%s: unable to flush cache\n", dksc->sc_xname);
 		return false;
 	}
 
@@ -300,90 +293,41 @@ static int
 ldopen(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	struct ld_softc *sc;
-	int error, unit, part;
+	struct dk_softc *dksc;
+	int unit;
 
 	unit = DISKUNIT(dev);
 	if ((sc = device_lookup_private(&ld_cd, unit)) == NULL)
 		return (ENXIO);
-	if ((sc->sc_flags & LDF_ENABLED) == 0)
-		return (ENODEV);
-	part = DISKPART(dev);
-
-	mutex_enter(&sc->sc_dk.dk_openlock);
-
-	if (sc->sc_dk.dk_openmask == 0) {
-		/* Load the partition info if not already loaded. */
-		if ((sc->sc_flags & LDF_VLABEL) == 0)
-			ldgetdisklabel(sc);
-	}
-
-	/* Check that the partition exists. */
-	if (part != RAW_PART && (part >= sc->sc_dk.dk_label->d_npartitions ||
-	    sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
-		error = ENXIO;
-		goto bad1;
-	}
-
-	/* Ensure only one open at a time. */
-	switch (fmt) {
-	case S_IFCHR:
-		sc->sc_dk.dk_copenmask |= (1 << part);
-		break;
-	case S_IFBLK:
-		sc->sc_dk.dk_bopenmask |= (1 << part);
-		break;
-	}
-	sc->sc_dk.dk_openmask =
-	    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
+	dksc = &sc->sc_dksc;
 
-	error = 0;
- bad1:
-	mutex_exit(&sc->sc_dk.dk_openlock);
-	return (error);
+	return dk_open(dksc, dev, flags, fmt, l);
 }
 
 static int
-ldlastclose(device_t self)
+ld_lastclose(device_t self)
 {
 	struct ld_softc *sc = device_private(self);
-
+		
 	if (sc->sc_flush != NULL && (*sc->sc_flush)(sc, 0) != 0)
 		aprint_error_dev(self, "unable to flush cache\n");
-	if ((sc->sc_flags & LDF_KLABEL) == 0)
-		sc->sc_flags &= ~LDF_VLABEL;
-
+	
 	return 0;
-}
+}               
 
 /* ARGSUSED */
 static int
 ldclose(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	struct ld_softc *sc;
-	int part, unit;
+	struct dk_softc *dksc;
+	int unit;
 
 	unit = DISKUNIT(dev);
-	part = DISKPART(dev);
 	sc = device_lookup_private(&ld_cd, unit);
+	dksc = &sc->sc_dksc;
 
-	mutex_enter(&sc->sc_dk.dk_openlock);
-
-	switch (fmt) {
-	case S_IFCHR:
-		sc->sc_dk.dk_copenmask &= ~(1 << part);
-		break;
-	case S_IFBLK:
-		sc->sc_dk.dk_bopenmask &= ~(1 << part);
-		break;
-	}
-	sc->sc_dk.dk_openmask =
-	    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
-
-	if (sc->sc_dk.dk_openmask == 0)
-		ldlastclose(sc->sc_dv);
-
-	mutex_exit(&sc->sc_dk.dk_openlock);
-	return (0);
+	return dk_close(dksc, dev, flags, fmt, l);
 }
 
 /* ARGSUSED */
@@ -407,89 +351,24 @@ static int
 ldioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l)
 {
 	struct ld_softc *sc;
+	struct dk_softc *dksc;
 	int unit, error;
-#ifdef __HAVE_OLD_DISKLABEL
-	struct disklabel newlabel;
-#endif
-	struct disklabel *lp;
 
 	unit = DISKUNIT(dev);
 	sc = device_lookup_private(&ld_cd, unit);
+	dksc = &sc->sc_dksc;
 
-	error = disk_ioctl(&sc->sc_dk, dev, cmd, addr, flag, l);
+	error = disk_ioctl(&dksc->sc_dkdev, dev, cmd, addr, flag, l);
 	if (error != EPASSTHROUGH)
 		return (error);
 
-	error = 0;
-	switch (cmd) {
-	case DIOCWDINFO:
-	case DIOCSDINFO:
-#ifdef __HAVE_OLD_DISKLABEL
-	case ODIOCWDINFO:
-	case ODIOCSDINFO:
-
-		if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
-			memset(&newlabel, 0, sizeof newlabel);
-			memcpy(&newlabel, addr, sizeof (struct olddisklabel));
-			lp = &newlabel;
-		} else
-#endif
-		lp = (struct disklabel *)addr;
-
-		if ((flag & FWRITE) == 0)
-			return (EBADF);
-
-		mutex_enter(&sc->sc_dk.dk_openlock);
-		sc->sc_flags |= LDF_LABELLING;
-
-		error = setdisklabel(sc->sc_dk.dk_label,
-		    lp, /*sc->sc_dk.dk_openmask : */0,
-		    sc->sc_dk.dk_cpulabel);
-		if (error == 0 && (cmd == DIOCWDINFO
-#ifdef __HAVE_OLD_DISKLABEL
-		    || cmd == ODIOCWDINFO
-#endif
-		    ))
-			error = writedisklabel(
-			    MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART),
-			    ldstrategy, sc->sc_dk.dk_label,
-			    sc->sc_dk.dk_cpulabel);
-
-		sc->sc_flags &= ~LDF_LABELLING;
-		mutex_exit(&sc->sc_dk.dk_openlock);
-		break;
-
-	case DIOCKLABEL:
-		if ((flag & FWRITE) == 0)
-			return (EBADF);
-		if (*(int *)addr)
-			sc->sc_flags |= LDF_KLABEL;
-		else
-			sc->sc_flags &= ~LDF_KLABEL;
-		break;
-
-	case DIOCWLABEL:
-		if ((flag & FWRITE) == 0)
-			return (EBADF);
-		if (*(int *)addr)
-			sc->sc_flags |= LDF_WLABEL;
-		else
-			sc->sc_flags &= ~LDF_WLABEL;
-		break;
-
-	case DIOCGDEFLABEL:
-		ldgetdefaultlabel(sc, (struct disklabel *)addr);
-		break;
+	error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
+	if (error != EPASSTHROUGH)
+		return (error);
 
-#ifdef __HAVE_OLD_DISKLABEL
-	case ODIOCGDEFLABEL:
-		ldgetdefaultlabel(sc, &newlabel);
-		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
-			return ENOTTY;
-		memcpy(addr, &newlabel, sizeof (struct olddisklabel));
-		break;
-#endif
+	error = 0;
 
+	switch (cmd) {
 	case DIOCCACHESYNC:
 		/*
 		 * XXX Do we really need to care about having a writable
@@ -502,45 +381,6 @@ ldioctl(dev_t dev, u_long cmd, void *add
 		else
 			error = 0;	/* XXX Error out instead? */
 		break;
-
-	case DIOCGSTRATEGY:
-	    {
-		struct disk_strategy *dks = (void *)addr;
-
-		mutex_enter(&sc->sc_mutex);
-		strlcpy(dks->dks_name, bufq_getstrategyname(sc->sc_bufq),
-		    sizeof(dks->dks_name));
-		mutex_exit(&sc->sc_mutex);
-		dks->dks_paramlen = 0;
-
-		return 0;
-	    }
-	case DIOCSSTRATEGY:
-	    {
-		struct disk_strategy *dks = (void *)addr;
-		struct bufq_state *new_bufq, *old_bufq;
-
-		if ((flag & FWRITE) == 0)
-			return EPERM;
-
-		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;
-
-		mutex_enter(&sc->sc_mutex);
-		old_bufq = sc->sc_bufq;
-		bufq_move(new_bufq, old_bufq);
-		sc->sc_bufq = new_bufq;
-		mutex_exit(&sc->sc_mutex);
-		bufq_free(old_bufq);
-
-		return 0;
-	    }
 	default:
 		error = ENOTTY;
 		break;
@@ -553,89 +393,32 @@ static void
 ldstrategy(struct buf *bp)
 {
 	struct ld_softc *sc;
-	struct disklabel *lp;
-	daddr_t blkno;
-	int s, part;
-
-	sc = device_lookup_private(&ld_cd, DISKUNIT(bp->b_dev));
-	part = DISKPART(bp->b_dev);
-
-	if ((sc->sc_flags & LDF_DETACH) != 0) {
-		bp->b_error = EIO;
-		goto done;
-	}
-
-	lp = sc->sc_dk.dk_label;
-
-	/*
-	 * The transfer must be a whole number of blocks and the 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 and adjust the transfer.  If error, process.
-	 * If past the end of partition, just return.
-	 */
-	if (part == RAW_PART) {
-		if (bounds_check_with_mediasize(bp, DEV_BSIZE,
-		    sc->sc_disksize512) <= 0)
-			goto done;
-	} else {
-		if (bounds_check_with_label(&sc->sc_dk, bp,
-		    (sc->sc_flags & (LDF_WLABEL | LDF_LABELLING)) != 0) <= 0)
-			goto done;
-	}
-
-	/*
-	 * 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);
-	else
-		blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
-
-	if (part != RAW_PART)
-		blkno += lp->d_partitions[part].p_offset;
-
-	bp->b_rawblkno = blkno;
+	struct dk_softc *dksc;
+	int unit;
 
-	s = splbio();
-	ldstart(sc, bp);
-	splx(s);
-	return;
+	unit = DISKUNIT(bp->b_dev);
+	sc = device_lookup_private(&ld_cd, unit);
+	dksc = &sc->sc_dksc;
 
- done:
-	bp->b_resid = bp->b_bcount;
-	biodone(bp);
+	return dk_strategy(dksc, bp);
 }
 
 static void
-ldstart(struct ld_softc *sc, struct buf *bp)
+ld_start(device_t dev)
 {
+	struct ld_softc *sc = device_private(dev);
+	struct dk_softc *dksc = &sc->sc_dksc;
+	struct buf *bp;
 	int error;
 
 	mutex_enter(&sc->sc_mutex);
 
-	if (bp != NULL)
-		bufq_put(sc->sc_bufq, bp);
-
 	while (sc->sc_queuecnt < sc->sc_maxqueuecnt) {
 		/* See if there is work to do. */
-		if ((bp = bufq_peek(sc->sc_bufq)) == NULL)
+		if ((bp = bufq_peek(dksc->sc_bufq)) == NULL)
 			break;
 
-		disk_busy(&sc->sc_dk);
+		disk_busy(&dksc->sc_dkdev);
 		sc->sc_queuecnt++;
 
 		if (__predict_true((error = (*sc->sc_start)(sc, bp)) == 0)) {
@@ -643,9 +426,9 @@ ldstart(struct ld_softc *sc, struct buf 
 			 * The back-end is running the job; remove it from
 			 * the queue.
 			 */
-			(void) bufq_get(sc->sc_bufq);
+			(void) bufq_get(dksc->sc_bufq);
 		} else  {
-			disk_unbusy(&sc->sc_dk, 0, (bp->b_flags & B_READ));
+			disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
 			sc->sc_queuecnt--;
 			if (error == EAGAIN) {
 				/*
@@ -658,7 +441,7 @@ ldstart(struct ld_softc *sc, struct buf 
 				 */
 				break;
 			} else {
-				(void) bufq_get(sc->sc_bufq);
+				(void) bufq_get(dksc->sc_bufq);
 				bp->b_error = error;
 				bp->b_resid = bp->b_bcount;
 				mutex_exit(&sc->sc_mutex);
@@ -674,16 +457,9 @@ ldstart(struct ld_softc *sc, struct buf 
 void
 lddone(struct ld_softc *sc, struct buf *bp)
 {
+	struct dk_softc *dksc = &sc->sc_dksc;
 
-	if (bp->b_error != 0) {
-		diskerr(bp, "ld", "error", LOG_PRINTF, 0, sc->sc_dk.dk_label);
-		printf("\n");
-	}
-
-	disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid,
-	    (bp->b_flags & B_READ));
-	rnd_add_uint32(&sc->sc_rnd_source, bp->b_rawblkno);
-	biodone(bp);
+	dk_done(dksc, bp);
 
 	mutex_enter(&sc->sc_mutex);
 	if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) {
@@ -692,7 +468,7 @@ lddone(struct ld_softc *sc, struct buf *
 			wakeup(&sc->sc_queuecnt);
 		}
 		mutex_exit(&sc->sc_mutex);
-		ldstart(sc, NULL);
+		ld_start(dksc->sc_dev);
 	} else
 		mutex_exit(&sc->sc_mutex);
 }
@@ -701,143 +477,50 @@ static int
 ldsize(dev_t dev)
 {
 	struct ld_softc *sc;
-	int part, unit, omask, size;
+	struct dk_softc *dksc;
+	int unit;
 
 	unit = DISKUNIT(dev);
 	if ((sc = device_lookup_private(&ld_cd, unit)) == NULL)
 		return (ENODEV);
+	dksc = &sc->sc_dksc;
+
 	if ((sc->sc_flags & LDF_ENABLED) == 0)
 		return (ENODEV);
-	part = DISKPART(dev);
-
-	omask = sc->sc_dk.dk_openmask & (1 << part);
-
-	if (omask == 0 && ldopen(dev, 0, S_IFBLK, NULL) != 0)
-		return (-1);
-	else if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
-		size = -1;
-	else
-		size = sc->sc_dk.dk_label->d_partitions[part].p_size *
-		    (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
-	if (omask == 0 && ldclose(dev, 0, S_IFBLK, NULL) != 0)
-		return (-1);
-
-	return (size);
-}
-
-/*
- * Load the label information from the specified device.
- */
-static void
-ldgetdisklabel(struct ld_softc *sc)
-{
-	const char *errstring;
-
-	ldgetdefaultlabel(sc, sc->sc_dk.dk_label);
-
-	/* Call the generic disklabel extraction routine. */
-	errstring = readdisklabel(MAKEDISKDEV(0, device_unit(sc->sc_dv),
-	    RAW_PART), ldstrategy, sc->sc_dk.dk_label, sc->sc_dk.dk_cpulabel);
-	if (errstring != NULL)
-		printf("%s: %s\n", device_xname(sc->sc_dv), errstring);
-
-	/* In-core label now valid. */
-	sc->sc_flags |= LDF_VLABEL;
-}
 
-/*
- * Construct a ficticious label.
- */
-static void
-ldgetdefaultlabel(struct ld_softc *sc, struct disklabel *lp)
-{
-
-	memset(lp, 0, sizeof(struct disklabel));
-
-	lp->d_secsize = sc->sc_secsize;
-	lp->d_ntracks = sc->sc_nheads;
-	lp->d_nsectors = sc->sc_nsectors;
-	lp->d_ncylinders = sc->sc_ncylinders;
-	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
-	lp->d_type = DKTYPE_LD;
-	strlcpy(lp->d_typename, "unknown", sizeof(lp->d_typename));
-	strlcpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
-	if (sc->sc_secperunit > UINT32_MAX)
-		lp->d_secperunit = UINT32_MAX;
-	else
-		lp->d_secperunit = sc->sc_secperunit;
-	lp->d_rpm = 7200;
-	lp->d_interleave = 1;
-	lp->d_flags = 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);
+	return dk_size(dksc, dev);
 }
 
 /*
  * Take a dump.
  */
 static int
-lddump(dev_t dev, daddr_t blkno, void *vav, size_t size)
+lddump(dev_t dev, daddr_t blkno, void *va, size_t size)
 {
-	char *va = vav;
 	struct ld_softc *sc;
-	struct disklabel *lp;
-	int unit, part, nsects, sectoff, towrt, nblk, maxblkcnt, rv;
-	static int dumping;
+	struct dk_softc *dksc;
+	int unit;
 
 	unit = DISKUNIT(dev);
 	if ((sc = device_lookup_private(&ld_cd, unit)) == NULL)
 		return (ENXIO);
+	dksc = &sc->sc_dksc;
+
 	if ((sc->sc_flags & LDF_ENABLED) == 0)
 		return (ENODEV);
+
+	return dk_dump(dksc, dev, blkno, va, size);
+}
+
+static int
+ld_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
+{
+	struct ld_softc *sc = device_private(dev);
+	
 	if (sc->sc_dump == NULL)
 		return (ENXIO);
 
-	/* Check if recursive dump; if so, punt. */
-	if (dumping)
-		return (EFAULT);
-	dumping = 1;
-
-	/* Convert to disk sectors.  Request must be a multiple of size. */
-	part = DISKPART(dev);
-	lp = sc->sc_dk.dk_label;
-	if ((size % lp->d_secsize) != 0)
-		return (EFAULT);
-	towrt = size / lp->d_secsize;
-	blkno = dbtob(blkno) / lp->d_secsize;	/* 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 + towrt) > nsects))
-		return (EINVAL);
-
-	/* Offset block number to start of partition. */
-	blkno += sectoff;
-
-	/* Start dumping and return when done. */
-	maxblkcnt = sc->sc_maxxfer / sc->sc_secsize - 1;
-	while (towrt > 0) {
-		nblk = min(maxblkcnt, towrt);
-
-		if ((rv = (*sc->sc_dump)(sc, va, blkno, nblk)) != 0)
-			return (rv);
-
-		towrt -= nblk;
-		blkno += nblk;
-		va += nblk * sc->sc_secsize;
-	}
-
-	dumping = 0;
-	return (0);
+	return (*sc->sc_dump)(sc, va, blkno, nblk);
 }
 
 /*
@@ -846,34 +529,78 @@ lddump(dev_t dev, daddr_t blkno, void *v
 static void
 ldminphys(struct buf *bp)
 {
+	int unit;
 	struct ld_softc *sc;
 
-	sc = device_lookup_private(&ld_cd, DISKUNIT(bp->b_dev));
+	unit = DISKUNIT(bp->b_dev);
+	sc = device_lookup_private(&ld_cd, unit);
 
-	if (bp->b_bcount > sc->sc_maxxfer)
-		bp->b_bcount = sc->sc_maxxfer;
+	ld_iosize(sc->sc_dv, &bp->b_bcount);
 	minphys(bp);
 }
 
 static void
-ld_set_geometry(struct ld_softc *ld)
+ld_iosize(device_t d, int *countp)
 {
-	struct disk_geom *dg = &ld->sc_dk.dk_geom;
+	struct ld_softc *sc = device_private(d);
 
-	memset(dg, 0, sizeof(*dg));
+	if (*countp > sc->sc_maxxfer)
+		*countp = sc->sc_maxxfer;
+}
+
+static void
+ld_fake_geometry(struct ld_softc *sc)
+{
+	uint64_t ncyl;
+
+	if (sc->sc_secperunit <= 528 * 2048)		/* 528MB */
+		sc->sc_nheads = 16;
+	else if (sc->sc_secperunit <= 1024 * 2048)	/* 1GB */
+		sc->sc_nheads = 32;
+	else if (sc->sc_secperunit <= 21504 * 2048)	/* 21GB */
+		sc->sc_nheads = 64;
+	else if (sc->sc_secperunit <= 43008 * 2048)	/* 42GB */
+		sc->sc_nheads = 128;
+	else
+		sc->sc_nheads = 255;
+
+	sc->sc_nsectors = 63;
+	sc->sc_ncylinders = INT_MAX;
+	ncyl = sc->sc_secperunit /
+	    (sc->sc_nheads * sc->sc_nsectors);
+	if (ncyl < INT_MAX)
+		sc->sc_ncylinders = (int)ncyl;
+}
+
+static void
+ld_set_geometry(struct ld_softc *sc)
+{
+	struct dk_softc *dksc = &sc->sc_dksc;
+	struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
+	char tbuf[9];
+
+	format_bytes(tbuf, sizeof(tbuf), sc->sc_secperunit *
+	    sc->sc_secsize);
+	aprint_normal_dev(dksc->sc_dev, "%s, %d cyl, %d head, %d sec, "
+	    "%d bytes/sect x %"PRIu64" sectors\n",
+	    tbuf, sc->sc_ncylinders, sc->sc_nheads,
+	    sc->sc_nsectors, sc->sc_secsize, sc->sc_secperunit);
 
-	dg->dg_secperunit = ld->sc_secperunit;
-	dg->dg_secsize = ld->sc_secsize;
-	dg->dg_nsectors = ld->sc_nsectors;
-	dg->dg_ntracks = ld->sc_nheads;
-	dg->dg_ncylinders = ld->sc_ncylinders;
+	memset(dg, 0, sizeof(*dg));
+	dg->dg_secperunit = sc->sc_secperunit;
+	dg->dg_secsize = sc->sc_secsize;
+	dg->dg_nsectors = sc->sc_nsectors;
+	dg->dg_ntracks = sc->sc_nheads;
+	dg->dg_ncylinders = sc->sc_ncylinders;
 
-	disk_set_info(ld->sc_dv, &ld->sc_dk, NULL);
+	disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
 }
 
 static void
 ld_config_interrupts(device_t d)
 {
 	struct ld_softc *sc = device_private(d);
-	dkwedge_discover(&sc->sc_dk);
+	struct dk_softc *dksc = &sc->sc_dksc;
+
+	dkwedge_discover(&dksc->sc_dkdev);
 }

Index: src/sys/dev/ldvar.h
diff -u src/sys/dev/ldvar.h:1.22 src/sys/dev/ldvar.h:1.23
--- src/sys/dev/ldvar.h:1.22	Mon Apr 13 16:33:23 2015
+++ src/sys/dev/ldvar.h	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ldvar.h,v 1.22 2015/04/13 16:33:23 riastradh Exp $	*/
+/*	$NetBSD: ldvar.h,v 1.23 2015/05/02 08:00:08 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -33,15 +33,15 @@
 #define	_DEV_LDVAR_H_
 
 #include <sys/mutex.h>
-#include <sys/device.h>	/* for device_t */
 #include <sys/rndsource.h>
 
+#include <dev/dkvar.h> /* for dk_softc */
+
 struct ld_softc {
-	device_t sc_dv;
-	struct	disk sc_dk;
-	struct	bufq_state *sc_bufq;
+	struct  dk_softc sc_dksc;
 	kmutex_t sc_mutex;
 	krndsource_t	sc_rnd_source;
+
 	int	sc_queuecnt;		/* current h/w queue depth */
 	int	sc_ncylinders;		/* # cylinders */
 	int	sc_nheads;		/* # heads */
@@ -51,7 +51,8 @@ struct ld_softc {
 	/*
 	 * The following are filled by hardware specific attachment code.
 	 */
-	int	sc_flags;		/* control flags */
+	device_t	sc_dv;
+	int     sc_flags;               /* control flags */
 	uint64_t	sc_secperunit;		/* # sectors in total */
 	int	sc_secsize;		/* sector size in bytes */
 	int	sc_maxxfer;		/* max xfer size in bytes */
@@ -64,12 +65,7 @@ struct ld_softc {
 
 /* sc_flags */
 #define	LDF_ENABLED	0x001		/* device enabled */
-#define	LDF_WLABEL	0x008		/* label is writable */
-#define	LDF_LABELLING	0x010		/* writing label */
 #define	LDF_DRAIN	0x020		/* maxqueuecnt has changed; drain */
-#define	LDF_DETACH	0x040		/* detach pending */
-#define	LDF_KLABEL	0x080		/* keep label on close */
-#define	LDF_VLABEL	0x100		/* label is valid */
 
 /* sc_flush() flags */
 #define	LDFL_POLL	0x001		/* poll for completion */

Index: src/sys/sys/disk.h
diff -u src/sys/sys/disk.h:1.63 src/sys/sys/disk.h:1.64
--- src/sys/sys/disk.h:1.63	Wed Dec 31 20:13:41 2014
+++ src/sys/sys/disk.h	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: disk.h,v 1.63 2014/12/31 20:13:41 mlelstv Exp $	*/
+/*	$NetBSD: disk.h,v 1.64 2015/05/02 08:00:08 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 2004 The NetBSD Foundation, Inc.
@@ -470,18 +470,18 @@ struct disk {
 	struct cpu_disklabel *dk_cpulabel;
 };
 
+#ifdef _KERNEL
 struct dkdriver {
 	void	(*d_strategy)(struct buf *);
 	void	(*d_minphys)(struct buf *);
-#ifdef notyet
-	int	(*d_open)(dev_t, int, int, struct proc *);
-	int	(*d_close)(dev_t, int, int, struct proc *);
-	int	(*d_ioctl)(dev_t, u_long, void *, int, struct proc *);
-	int	(*d_dump)(dev_t);
-	void	(*d_start)(struct buf *, daddr_t);
-	int	(*d_mklabel)(struct disk *);
-#endif
+	int	(*d_open)(dev_t, int, int, struct lwp *);
+	int	(*d_close)(dev_t, int, int, struct lwp *);
+	void	(*d_diskstart)(device_t);
+	void	(*d_iosize)(device_t, int *);
+	int	(*d_dumpblocks)(device_t, void *, daddr_t, int);
+	int	(*d_lastclose)(device_t);
 };
+#endif
 
 /* states */
 #define	DK_CLOSED	0		/* drive is closed */

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.475 src/sys/sys/param.h:1.476
--- src/sys/sys/param.h:1.475	Sun Apr 26 21:40:49 2015
+++ src/sys/sys/param.h	Sat May  2 08:00:08 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.475 2015/04/26 21:40:49 rtr Exp $	*/
+/*	$NetBSD: param.h,v 1.476 2015/05/02 08:00:08 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -63,7 +63,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	799001300	/* NetBSD 7.99.13 */
+#define	__NetBSD_Version__	799001400	/* NetBSD 7.99.14 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Reply via email to