install approved copyright notice
[unix-history] / usr / src / sys / tahoe / vba / vd.c
index 9541c8a..63709a7 100644 (file)
@@ -1,4 +1,21 @@
-/*     vd.c    1.18    87/04/02        */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)vd.c        7.5 (Berkeley) %G%
+ */
 
 #include "dk.h"
 #if NVD > 0
 
 #include "dk.h"
 #if NVD > 0
 #include "../tahoevba/vbavar.h"
 #include "../tahoevba/vdreg.h"
 
 #include "../tahoevba/vbavar.h"
 #include "../tahoevba/vdreg.h"
 
+#ifndef        COMPAT_42
 #define        COMPAT_42
 #define        COMPAT_42
+#endif
+#define        B_FORMAT        B_XXX           /* XXX */
 
 #define vdunit(dev)    (minor(dev) >> 3)
 #define vdpart(dev)    (minor(dev) & 0x07)
 
 #define vdunit(dev)    (minor(dev) >> 3)
 #define vdpart(dev)    (minor(dev) & 0x07)
@@ -40,9 +60,9 @@
 struct vba_ctlr *vdminfo[NVD];
 struct  vba_device *vddinfo[NDK];
 int    vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();
 struct vba_ctlr *vdminfo[NVD];
 struct  vba_device *vddinfo[NDK];
 int    vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();
-long   vdaddr[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
+long   vdstd[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
 struct vba_driver vddriver =
 struct vba_driver vddriver =
-  { vdprobe, vdslave, vdattach, vddgo, vdaddr, "dk", vddinfo, "vd", vdminfo };
+  { vdprobe, vdslave, vdattach, vddgo, vdstd, "dk", vddinfo, "vd", vdminfo };
 
 /*
  * Per-controller state.
 
 /*
  * Per-controller state.
@@ -62,26 +82,30 @@ struct vdsoftc {
        struct  vb_buf vd_rbuf; /* vba resources */
 } vdsoftc[NVD];
 
        struct  vb_buf vd_rbuf; /* vba resources */
 } vdsoftc[NVD];
 
+#define        VDMAXTIME       20      /* max time for operation, sec. */
+
 /*
  * Per-drive state.
  */
 struct dksoftc {
 /*
  * Per-drive state.
  */
 struct dksoftc {
-       u_short dk_state;       /* open fsm */
-       u_short dk_copenpart;   /* character units open on this drive */
-       u_short dk_bopenpart;   /* block units open on this drive */
-       u_short dk_openpart;    /* all units open on this drive */
+       int     dk_state;       /* open fsm */
 #ifndef SECSIZE
        u_short dk_bshift;      /* shift for * (DEV_BSIZE / sectorsize) XXX */
 #endif SECSIZE
 #ifndef SECSIZE
        u_short dk_bshift;      /* shift for * (DEV_BSIZE / sectorsize) XXX */
 #endif SECSIZE
+       int     dk_wlabel;      /* label sector is currently writable */
+       u_long  dk_copenpart;   /* character units open on this drive */
+       u_long  dk_bopenpart;   /* block units open on this drive */
+       u_long  dk_openpart;    /* all units open on this drive */
        u_int   dk_curcyl;      /* last selected cylinder */
        struct  skdcb dk_dcb;   /* seek command block */
        u_long  dk_dcbphys;     /* physical address of dk_dcb */
        u_int   dk_curcyl;      /* last selected cylinder */
        struct  skdcb dk_dcb;   /* seek command block */
        u_long  dk_dcbphys;     /* physical address of dk_dcb */
+       int     df_reg[3];      /* for formatting, in-out parameters */
 } dksoftc[NDK];
 
 /*
  * Drive states.  Used during steps of open/initialization.
  * States < OPEN (> 0) are transient, during an open operation.
 } dksoftc[NDK];
 
 /*
  * Drive states.  Used during steps of open/initialization.
  * States < OPEN (> 0) are transient, during an open operation.
- * OPENRAW is used for unabeled disks, to allow format operations.
+ * OPENRAW is used for unlabeled disks, to allow format operations.
  */
 #define        CLOSED          0               /* disk is closed */
 #define        WANTOPEN        1               /* open requested, not started */
  */
 #define        CLOSED          0               /* disk is closed */
 #define        WANTOPEN        1               /* open requested, not started */
@@ -90,7 +114,6 @@ struct       dksoftc {
 #define        OPEN            4               /* intialized and ready */
 #define        OPENRAW         5               /* open, no label */
 
 #define        OPEN            4               /* intialized and ready */
 #define        OPENRAW         5               /* open, no label */
 
-struct buf rdkbuf[NDK];        /* raw i/o buffer headers */
 struct buf dkutab[NDK];        /* i/o queue headers */
 struct disklabel dklabel[NDK]; /* pack labels */
 
 struct buf dkutab[NDK];        /* i/o queue headers */
 struct disklabel dklabel[NDK]; /* pack labels */
 
@@ -162,8 +185,11 @@ vdprobe(reg, vm)
        /*
         * Allocate page tables and i/o buffer.
         */
        /*
         * Allocate page tables and i/o buffer.
         */
-       vbainit(&vd->vd_rbuf, MAXPHYS,
-           vd->vd_type == VDTYPE_VDDC ? VB_24BIT : VB_32BIT);
+       if (vbainit(&vd->vd_rbuf, MAXPHYS,
+           vd->vd_type == VDTYPE_VDDC ? VB_24BIT : VB_32BIT) == 0) {
+               printf("vd%d: vbainit failed\n", vm->um_ctlr);
+               return (0);
+       }
        br = 0x17, cvec = 0xe0 + vm->um_ctlr;   /* XXX */
        return (sizeof (struct vddevice));
 }
        br = 0x17, cvec = 0xe0 + vm->um_ctlr;   /* XXX */
        return (sizeof (struct vddevice));
 }
@@ -176,11 +202,13 @@ vdprobe(reg, vm)
  * manner.  Instead just probe for the drive and leave
  * the pack label stuff to the attach routine.
  */
  * manner.  Instead just probe for the drive and leave
  * the pack label stuff to the attach routine.
  */
-vdslave(vi, addr)
+/* ARGSUSED */
+vdslave(vi, vdaddr)
        register struct vba_device *vi;
        struct vddevice *vdaddr;
 {
        register struct disklabel *lp = &dklabel[vi->ui_unit];
        register struct vba_device *vi;
        struct vddevice *vdaddr;
 {
        register struct disklabel *lp = &dklabel[vi->ui_unit];
+       register struct dksoftc *dk = &dksoftc[vi->ui_unit];
        struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
 
        if ((vd->vd_flags&VD_INIT) == 0) {
        struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
 
        if ((vd->vd_flags&VD_INIT) == 0) {
@@ -196,20 +224,17 @@ vdslave(vi, addr)
         * label values will be filled in in vdinit
         * at attach time.
         */
         * label values will be filled in in vdinit
         * at attach time.
         */
-       lp->d_secsize = DEV_BSIZE / 2;          /* XXX */
-       lp->d_nsectors = 32;
-       lp->d_ntracks = 24;
-       lp->d_ncylinders = 711;
-       lp->d_secpercyl = 32*24;
-       return (vdreset_drive(vi));
-}
-
-vdattach(vi)
-       register struct vba_device *vi;
-{
-       register int unit = vi->ui_unit;
-       register struct dksoftc *dk = &dksoftc[unit];
-       register struct disklabel *lp;
+       if (vd->vd_type == VDTYPE_SMDE)
+               lp->d_secsize = VD_MAXSECSIZE;
+       else
+               lp->d_secsize = VDDC_SECSIZE;
+       lp->d_nsectors = 66;            /* only used on smd-e */
+       lp->d_ntracks = 23;
+       lp->d_ncylinders = 850;
+       lp->d_secpercyl = 66*23;
+       lp->d_npartitions = 1;
+       lp->d_partitions[0].p_offset = 0;
+       lp->d_partitions[0].p_size = LABELSECTOR + 1;
 
        /*
         * Initialize invariant portion of
 
        /*
         * Initialize invariant portion of
@@ -221,6 +246,18 @@ vdattach(vi)
        dk->dk_dcb.trailcnt = sizeof (struct trseek) / sizeof (long);
        dk->dk_dcb.trail.sktrail.skaddr.sector = 0;
        dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);
        dk->dk_dcb.trailcnt = sizeof (struct trseek) / sizeof (long);
        dk->dk_dcb.trail.sktrail.skaddr.sector = 0;
        dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);
+#ifndef SECSIZE
+       vd_setsecsize(dk, lp);
+#endif
+       return (vdreset_drive(vi));
+}
+
+vdattach(vi)
+       register struct vba_device *vi;
+{
+       register int unit = vi->ui_unit;
+       register struct disklabel *lp = &dklabel[unit];
+
        /*
         * Try to initialize device and read pack label.
         */
        /*
         * Try to initialize device and read pack label.
         */
@@ -228,9 +265,10 @@ vdattach(vi)
                printf(": unknown drive type");
                return;
        }
                printf(": unknown drive type");
                return;
        }
-       lp = &dklabel[unit];
-       printf(": %s <ntrak %d, ncyl %d, nsec %d>",
-           lp->d_typename, lp->d_ntracks, lp->d_ncylinders, lp->d_nsectors);
+       if (dksoftc[unit].dk_state == OPEN)
+               printf(": %s <secsize %d, ntrak %d, ncyl %d, nsec %d>",
+                   lp->d_typename, lp->d_secsize,
+                   lp->d_ntracks, lp->d_ncylinders, lp->d_nsectors);
        /*
         * (60 / rpm) / (sectors per track * (bytes per sector / 2))
         */
        /*
         * (60 / rpm) / (sectors per track * (bytes per sector / 2))
         */
@@ -277,9 +315,8 @@ vdopen(dev, flags, fmt)
         * that overlaps another partition which is open
         * unless one is the "raw" partition (whole disk).
         */
         * that overlaps another partition which is open
         * unless one is the "raw" partition (whole disk).
         */
-#define        RAWPART         2               /* 'c' partition */     /* XXX */
-       if ((dk->dk_openpart & (1 << part)) == 0 &&
-           part != RAWPART) {
+#define        RAWPART         8               /* 'x' partition */     /* XXX */
+       if ((dk->dk_openpart & mask) == 0 && part != RAWPART) {
                pp = &lp->d_partitions[part];
                start = pp->p_offset;
                end = pp->p_offset + pp->p_size;
                pp = &lp->d_partitions[part];
                start = pp->p_offset;
                end = pp->p_offset + pp->p_size;
@@ -311,6 +348,7 @@ vdopen(dev, flags, fmt)
        return (0);
 }
 
        return (0);
 }
 
+/* ARGSUSED */
 vdclose(dev, flags, fmt)
        dev_t dev;
        int flags, fmt;
 vdclose(dev, flags, fmt)
        dev_t dev;
        int flags, fmt;
@@ -339,6 +377,7 @@ vdclose(dev, flags, fmt)
                        sleep((caddr_t)dk, PZERO-1);
                splx(s);
                dk->dk_state = CLOSED;
                        sleep((caddr_t)dk, PZERO-1);
                splx(s);
                dk->dk_state = CLOSED;
+               dk->dk_wlabel = 0;
        }
        return (0);
 }
        }
        return (0);
 }
@@ -355,56 +394,62 @@ vdinit(dev, flags)
        extern int cold;
 
        dk = &dksoftc[unit];
        extern int cold;
 
        dk = &dksoftc[unit];
-#ifndef SECSIZE
-       dk->dk_bshift = 1;              /* DEV_BSIZE / 512 */
-#endif SECSIZE
        if (flags & O_NDELAY) {
                dk->dk_state = OPENRAW;
        if (flags & O_NDELAY) {
                dk->dk_state = OPENRAW;
-               return;
+               return (0);
        }
        dk->dk_state = RDLABEL;
        lp = &dklabel[unit];
        vi = vddinfo[unit];
        if (msg = readdisklabel(dev, vdstrategy, lp)) {
        }
        dk->dk_state = RDLABEL;
        lp = &dklabel[unit];
        vi = vddinfo[unit];
        if (msg = readdisklabel(dev, vdstrategy, lp)) {
-               if (cold)
+               if (cold) {
                        printf(": %s", msg);
                        printf(": %s", msg);
-               else
-                       log(LOG_ERR, "dk%d: %s\n", vi->ui_unit, msg);
-#ifdef COMPAT_42
-               if (!vdmaptype(vi, lp))
+                       dk->dk_state = CLOSED;
+               } else {
+                       log(LOG_ERR, "dk%d: %s\n", unit, msg);
                        dk->dk_state = OPENRAW;
                        dk->dk_state = OPENRAW;
-               else
+               }
+#ifdef COMPAT_42
+               if (vdmaptype(vi, lp))
                        dk->dk_state = OPEN;
                        dk->dk_state = OPEN;
-#else
-               dk->dk_state = OPENRAW;
 #endif
        } else {
                /*
                 * Now that we have the label, configure
                 * the correct drive parameters.
                 */
 #endif
        } else {
                /*
                 * Now that we have the label, configure
                 * the correct drive parameters.
                 */
-               if (!vdreset_drive(vi)) {
+               if (vdreset_drive(vi))
+                       dk->dk_state = OPEN;
+               else {
                        dk->dk_state = CLOSED;
                        error = ENXIO;
                        dk->dk_state = CLOSED;
                        error = ENXIO;
-               } else
-                       dk->dk_state = OPEN;
+               }
        }
 #ifndef SECSIZE
        }
 #ifndef SECSIZE
-       /*
-        * If open, calculate scaling shift for
-        * mapping DEV_BSIZE blocks to drive sectors.
-        */
-       if (dk->dk_state == OPEN || dk->dk_state == OPENRAW) {
-               int mul = DEV_BSIZE / lp->d_secsize;
-               dk->dk_bshift = 0;
-               while ((mul >>= 1) > 0)
-                       dk->dk_bshift++;
-       }
-#endif SECSIZE
+       vd_setsecsize(dk, lp);
+#endif
        wakeup((caddr_t)dk);
        return (error);
 }
 
        wakeup((caddr_t)dk);
        return (error);
 }
 
+#ifndef SECSIZE
+vd_setsecsize(dk, lp)
+       register struct dksoftc *dk;
+       register struct disklabel *lp;
+{
+       int mul;
+
+       /*
+        * Calculate scaling shift for mapping
+        * DEV_BSIZE blocks to drive sectors.
+        */
+       mul = DEV_BSIZE / lp->d_secsize;
+       dk->dk_bshift = 0;
+       while ((mul >>= 1) > 0)
+               dk->dk_bshift++;
+}
+#endif SECSIZE
+
 /*ARGSUSED*/
 vddgo(vm)
        struct vba_device *vm;
 /*ARGSUSED*/
 vddgo(vm)
        struct vba_device *vm;
@@ -425,7 +470,7 @@ vdstrategy(bp)
        int part, s;
 
        unit = vdunit(bp->b_dev);
        int part, s;
 
        unit = vdunit(bp->b_dev);
-       if (unit > NDK) {
+       if (unit >= NDK) {
                bp->b_error = ENXIO;
                goto bad;
        }
                bp->b_error = ENXIO;
                goto bad;
        }
@@ -435,21 +480,33 @@ vdstrategy(bp)
                bp->b_error = ENXIO;
                goto bad;
        }
                bp->b_error = ENXIO;
                goto bad;
        }
-       sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
        dk = &dksoftc[unit];
        if (dk->dk_state < OPEN)
                goto q;
        dk = &dksoftc[unit];
        if (dk->dk_state < OPEN)
                goto q;
+       if (dk->dk_state != OPEN && (bp->b_flags & B_READ) == 0) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
        part = vdpart(bp->b_dev);
        if ((dk->dk_openpart & (1 << part)) == 0) {
                bp->b_error = ENODEV;
                goto bad;
        }
        part = vdpart(bp->b_dev);
        if ((dk->dk_openpart & (1 << part)) == 0) {
                bp->b_error = ENODEV;
                goto bad;
        }
+       sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
        maxsz = lp->d_partitions[part].p_size;
 #ifndef SECSIZE
        sn = bp->b_blkno << dk->dk_bshift;
 #else SECSIZE
        sn = bp->b_blkno;
 #endif SECSIZE
        maxsz = lp->d_partitions[part].p_size;
 #ifndef SECSIZE
        sn = bp->b_blkno << dk->dk_bshift;
 #else SECSIZE
        sn = bp->b_blkno;
 #endif SECSIZE
+       if (sn + lp->d_partitions[part].p_offset <= LABELSECTOR &&
+#if LABELSECTOR != 0
+           sn + lp->d_partitions[part].p_offset + sz > LABELSECTOR &&
+#endif
+           (bp->b_flags & B_READ) == 0 && dk->dk_wlabel == 0) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
        if (sn < 0 || sn + sz > maxsz) {
                if (sn == maxsz) {
                        bp->b_resid = bp->b_bcount;
        if (sn < 0 || sn + sz > maxsz) {
                if (sn == maxsz) {
                        bp->b_resid = bp->b_bcount;
@@ -545,9 +602,7 @@ vdstart(vm)
        register struct vdsoftc *vd;
        register struct dksoftc *dk;
        register struct disklabel *lp;
        register struct vdsoftc *vd;
        register struct dksoftc *dk;
        register struct disklabel *lp;
-       register int slave;
        register struct dcb **dcbp;
        register struct dcb **dcbp;
-       struct mdcb *mdcb;
        struct buf *dp;
        int sn, tn;
 
        struct buf *dp;
        int sn, tn;
 
@@ -587,9 +642,8 @@ loop:
         * Construct dcb for read/write command.
         */
        vd = &vdsoftc[vm->um_ctlr];
         * Construct dcb for read/write command.
         */
        vd = &vdsoftc[vm->um_ctlr];
-       slave = vi->ui_slave;
        vd->vd_dcb.intflg = DCBINT_DONE;
        vd->vd_dcb.intflg = DCBINT_DONE;
-       vd->vd_dcb.devselect = slave;
+       vd->vd_dcb.devselect = dk->dk_dcb.devselect;
        vd->vd_dcb.operrsta = 0;
        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
        vd->vd_dcb.operrsta = 0;
        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
@@ -598,16 +652,37 @@ loop:
        dk->dk_curcyl = bp->b_cylin;
        bp->b_track = 0;                /* init overloaded field */
        vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        dk->dk_curcyl = bp->b_cylin;
        bp->b_track = 0;                /* init overloaded field */
        vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
-       if (vd->vd_flags & VD_SCATGATH &&
-           ((int)bp->b_un.b_addr & (sizeof(long) - 1)) == 0) {
+       if (bp->b_flags & B_FORMAT)
+               vd->vd_dcb.opcode = dk->dk_op;
+       else if (vd->vd_flags & VD_SCATGATH &&
+           ((int)bp->b_un.b_addr & (sizeof(long) - 1)) == 0)
                vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RAS : VDOP_GAW;
                vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RAS : VDOP_GAW;
-               vd->vd_dcb.trailcnt += vba_sgsetup(bp, &vd->vd_rbuf,
-                   &vd->vd_dcb.trail.sgtrail);
-       } else {
+       else
                vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RD : VDOP_WD;
                vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RD : VDOP_WD;
-               vd->vd_dcb.trail.rwtrail.memadr =
-                       vbasetup(bp, &vd->vd_rbuf, lp->d_secsize);
+
+       switch (vd->vd_dcb.opcode) {
+       case VDOP_FSECT:
+               vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
+               vd->vd_dcb.trail.fmtrail.nsectors = bp->b_bcount /
+                   lp->d_secsize;
+               vd->vd_dcb.trail.fmtrail.hdr = *(dskadr *)&dk->dk_althdr;
+               vd->vd_dcb.trail.rwtrail.disk.cylinder |= dk->dk_fmtflags;
+               goto setupaddr;
+
+       case VDOP_RDRAW:
+       case VDOP_RD:
+       case VDOP_WD:
                vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
                vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
+setupaddr:
+               vd->vd_dcb.trail.rwtrail.memadr =
+                       vbasetup(bp, &vd->vd_rbuf, (int)lp->d_secsize);
+               break;
+
+       case VDOP_RAS:
+       case VDOP_GAW:
+               vd->vd_dcb.trailcnt += vba_sgsetup(bp, &vd->vd_rbuf,
+                   &vd->vd_dcb.trail.sgtrail);
+               break;
        }
        if (vi->ui_dk >= 0) {
                dk_busy |= 1<<vi->ui_dk;
        }
        if (vi->ui_dk >= 0) {
                dk_busy |= 1<<vi->ui_dk;
@@ -668,10 +743,9 @@ vdintr(ctlr)
        register struct vba_device *vi;
        register struct vdsoftc *vd = &vdsoftc[ctlr];
        register status;
        register struct vba_device *vi;
        register struct vdsoftc *vd = &vdsoftc[ctlr];
        register status;
-       int ecode;
+       int timedout;
        struct dksoftc *dk;
 
        struct dksoftc *dk;
 
-       vd->vd_wticks = 0;
        if (!vm->um_tab.b_active) {
                printf("vd%d: stray interrupt\n", ctlr);
                return;
        if (!vm->um_tab.b_active) {
                printf("vd%d: stray interrupt\n", ctlr);
                return;
@@ -683,53 +757,69 @@ vdintr(ctlr)
        dp = vm->um_tab.b_actf;
        bp = dp->b_actf;
        vi = vddinfo[vdunit(bp->b_dev)];
        dp = vm->um_tab.b_actf;
        bp = dp->b_actf;
        vi = vddinfo[vdunit(bp->b_dev)];
+       dk = &dksoftc[vi->ui_unit];
        if (vi->ui_dk >= 0)
                dk_busy &= ~(1<<vi->ui_dk);
        if (vi->ui_dk >= 0)
                dk_busy &= ~(1<<vi->ui_dk);
+       timedout = (vd->vd_wticks >= VDMAXTIME);
        /*
         * Check for and process errors on
         * either the drive or the controller.
         */
        uncache(&vd->vd_dcb.operrsta);
        status = vd->vd_dcb.operrsta;
        /*
         * Check for and process errors on
         * either the drive or the controller.
         */
        uncache(&vd->vd_dcb.operrsta);
        status = vd->vd_dcb.operrsta;
-       if (status & VDERR_HARD) {
-               if (vd->vd_type == VDTYPE_SMDE) {
+       if (bp->b_flags & B_FORMAT) {
+               dk->dk_operrsta = status;
+               uncache(&vd->vd_dcb.err_code);
+               dk->dk_ecode = vd->vd_dcb.err_code;
+       }
+       if (status & VDERR_HARD || timedout) {
+               if (vd->vd_type == VDTYPE_SMDE)
                        uncache(&vd->vd_dcb.err_code);
                        uncache(&vd->vd_dcb.err_code);
-                       ecode = vd->vd_dcb.err_code;
-               }
                if (status & DCBS_WPT) {
                        /*
                         * Give up on write locked devices immediately.
                         */
                        printf("dk%d: write locked\n", vi->ui_unit);
                        bp->b_flags |= B_ERROR;
                if (status & DCBS_WPT) {
                        /*
                         * Give up on write locked devices immediately.
                         */
                        printf("dk%d: write locked\n", vi->ui_unit);
                        bp->b_flags |= B_ERROR;
-               } else if (status & VDERR_RETRY) {
-                       if (status & VDERR_DRIVE) {
+               } else if (status & VDERR_RETRY || timedout) {
+                       int endline = 1;
+
+                       if (status & VDERR_CTLR || timedout) {
+                               vdharderr("controller err",
+                                   vd, bp, &vd->vd_dcb);
+                               printf("; resetting controller...");
+                               vdreset_ctlr(vm);
+                       } else if (status & VDERR_DRIVE) {
+                               vdharderr("drive err", vd, bp, &vd->vd_dcb);
+                               printf("; resetting drive...");
                                if (!vdreset_drive(vi))
                                        vi->ui_alive = 0;
                                if (!vdreset_drive(vi))
                                        vi->ui_alive = 0;
-                       } else if (status & VDERR_CTLR)
-                               vdreset_ctlr(vm);
+                       } else
+                               endline = 0;
                        /*
                         * Retry transfer once, unless reset failed.
                         */
                        /*
                         * Retry transfer once, unless reset failed.
                         */
-                       if (!vi->ui_alive || bp->b_errcnt++ >= 2)
+                       if (!vi->ui_alive || dp->b_errcnt++ >= 2 ||
+                           bp->b_flags & B_FORMAT) {
+                               if (endline)
+                                       printf("\n");
                                goto hard;
                                goto hard;
+                       }
+
+                       if (endline)
+                               printf(" retrying\n");
                        vm->um_tab.b_active = 0;        /* force retry */
                } else  {
        hard:
                        bp->b_flags |= B_ERROR;
                        vm->um_tab.b_active = 0;        /* force retry */
                } else  {
        hard:
                        bp->b_flags |= B_ERROR;
-                       /* NEED TO ADJUST b_blkno to failed sector */
-                       harderr(bp, "dk");
-                       printf("status %x (%b)", status,
-                          status &~ DONTCARE, VDERRBITS);
-                       if (vd->vd_type == VDTYPE_SMDE)
-                               printf(" ecode %x", ecode);
+                       vdharderr("hard error", vd, bp, &vd->vd_dcb);
                        printf("\n");
                }
        } else if (status & DCBS_SOFT)
                        printf("\n");
                }
        } else if (status & DCBS_SOFT)
-               vdsofterr(vd, bp, &vd->vd_dcb);
+               vdsofterr(bp, &vd->vd_dcb);
+       vd->vd_wticks = 0;
        if (vm->um_tab.b_active) {
                vm->um_tab.b_active = 0;
        if (vm->um_tab.b_active) {
                vm->um_tab.b_active = 0;
-               vm->um_tab.b_errcnt = 0;
                vm->um_tab.b_actf = dp->b_forw;
                dp->b_active = 0;
                dp->b_errcnt = 0;
                vm->um_tab.b_actf = dp->b_forw;
                dp->b_active = 0;
                dp->b_errcnt = 0;
@@ -743,7 +833,7 @@ vdintr(ctlr)
                 */
                if (dp->b_actf)
                        vdustart(vi);
                 */
                if (dp->b_actf)
                        vdustart(vi);
-               else if ((dk = &dksoftc[vi->ui_unit])->dk_openpart == 0)
+               else if (dk->dk_openpart == 0)
                        wakeup((caddr_t)dk);
        }
        /*
                        wakeup((caddr_t)dk);
        }
        /*
@@ -754,44 +844,50 @@ vdintr(ctlr)
                vdstart(vm);
 }
 
                vdstart(vm);
 }
 
-vdsofterr(vd, bp, dcb)
+vdharderr(what, vd, bp, dcb)
+       char *what;
        struct vdsoftc *vd;
        register struct buf *bp;
        register struct dcb *dcb;
 {
        int unit = vdunit(bp->b_dev), status = dcb->operrsta;
        struct vdsoftc *vd;
        register struct buf *bp;
        register struct dcb *dcb;
 {
        int unit = vdunit(bp->b_dev), status = dcb->operrsta;
-       char part = 'a' + vdpart(bp->b_dev);
-
-       if (status != (DCBS_CCD|DCBS_SOFT|DCBS_ERR|DCBS_DONE)) {
-               if (vd->vd_type == VDTYPE_SMDE)
-                       uncache(&dcb->err_code);
-               log(LOG_WARNING, "dk%d%c: soft error sn%d status %b ecode %x\n",
-                   unit, part, bp->b_blkno, status, VDERRBITS, dcb->err_code);
-       } else
-               log(LOG_WARNING, "dk%d%c: soft ecc sn%d\n",
-                   unit, part, bp->b_blkno);
+       register struct disklabel *lp = &dklabel[unit];
+       int blkdone;
+
+       if (vd->vd_wticks < VDMAXTIME)
+               status &= ~DONTCARE;
+       blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
+           lp->d_nsectors + dcb->err_sec -
+           lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
+           dksoftc[unit].dk_bshift) - bp->b_blkno;
+       diskerr(bp, "dk", what, LOG_PRINTF, blkdone, lp);
+       printf(", status %b", status, VDERRBITS);
+       if (vd->vd_type == VDTYPE_SMDE)
+               printf(" ecode %x", dcb->err_code);
 }
 
 }
 
-vdread(dev, uio)
-       dev_t dev;
-       struct uio *uio;
+vdsofterr(bp, dcb)
+       register struct buf *bp;
+       register struct dcb *dcb;
 {
 {
-       register int unit = vdunit(dev);
+       int unit = vdunit(bp->b_dev);
+       struct disklabel *lp = &dklabel[unit];
+       int status = dcb->operrsta;
+       int blkdone;
 
 
-       if (unit >= NDK)
-               return (ENXIO);
-       return (physio(vdstrategy, &rdkbuf[unit], dev, B_READ, minphys, uio));
-}
-
-vdwrite(dev, uio)
-       dev_t dev;
-       struct uio *uio;
-{
-       register int unit = vdunit(dev);
+       blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
+           lp->d_nsectors + dcb->err_sec -
+           lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
+           dksoftc[unit].dk_bshift) - bp->b_blkno;
 
 
-       if (unit >= NDK)
-               return (ENXIO);
-       return (physio(vdstrategy, &rdkbuf[unit], dev, B_WRITE, minphys, uio));
+       if (status != (DCBS_CCD|DCBS_SOFT|DCBS_ERR|DCBS_DONE)) {
+               diskerr(bp, "dk", "soft error", LOG_WARNING, blkdone, lp);
+               addlog(", status %b ecode %x\n", status, VDERRBITS,
+                   dcb->err_code);
+       } else {
+               diskerr(bp, "dk", "soft ecc", LOG_WARNING, blkdone, lp);
+               addlog("\n");
+       }
 }
 
 vdioctl(dev, cmd, data, flag)
 }
 
 vdioctl(dev, cmd, data, flag)
@@ -800,9 +896,10 @@ vdioctl(dev, cmd, data, flag)
        caddr_t data;
        int flag;
 {
        caddr_t data;
        int flag;
 {
-       int unit = vdunit(dev);
+       register int unit = vdunit(dev);
        register struct disklabel *lp = &dklabel[unit];
        register struct disklabel *lp = &dklabel[unit];
-       int error = 0;
+       register struct dksoftc *dk = &dksoftc[unit];
+       int error = 0, vdformat();
 
        switch (cmd) {
 
 
        switch (cmd) {
 
@@ -820,49 +917,83 @@ vdioctl(dev, cmd, data, flag)
                if ((flag & FWRITE) == 0)
                        error = EBADF;
                else
                if ((flag & FWRITE) == 0)
                        error = EBADF;
                else
-                       *lp = *(struct disklabel *)data;
+                       error = setdisklabel(lp, (struct disklabel *)data,
+                           (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart);
+               if (error == 0 && dk->dk_state == OPENRAW &&
+                   vdreset_drive(vddinfo[unit]))
+                       dk->dk_state = OPEN;
                break;
 
                break;
 
-       case DIOCWDINFO: {
-               struct buf *bp;
-               struct disklabel *dlp;
+       case DIOCWLABEL:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       dk->dk_wlabel = *(int *)data;
+               break;
+
+       case DIOCWDINFO:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else if ((error = setdisklabel(lp, (struct disklabel *)data,
+                   (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {
+                       int wlab;
+
+                       dk->dk_state = OPEN;
+                       /* simulate opening partition 0 so write succeeds */
+                       dk->dk_openpart |= (1 << 0);            /* XXX */
+                       wlab = dk->dk_wlabel;
+                       dk->dk_wlabel = 1;
+                       error = writedisklabel(dev, vdstrategy, lp);
+                       dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
+                       dk->dk_wlabel = wlab;
+               }
+               break;
+
+       case DIOCWFORMAT:
+           {
+               register struct format_op *fop;
+               struct uio auio;
+               struct iovec aiov;
 
                if ((flag & FWRITE) == 0) {
                        error = EBADF;
                        break;
                }
 
                if ((flag & FWRITE) == 0) {
                        error = EBADF;
                        break;
                }
-               *lp = *(struct disklabel *)data;
-               bp = geteblk(lp->d_secsize);
-               bp->b_dev = makedev(major(dev), vdminor(vdunit(dev), 0));
-               bp->b_blkno = LABELSECTOR;
-               bp->b_bcount = lp->d_secsize;
-               bp->b_flags = B_READ;
-               dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
-               vdstrategy(bp);
-               biowait(bp);
-               if (bp->b_flags & B_ERROR) {
-                       error = u.u_error;              /* XXX */
-                       u.u_error = 0;
-                       goto bad;
-               }
-               *dlp = *lp;
-               bp->b_flags = B_WRITE;
-               vdstrategy(bp);
-               biowait(bp);
-               if (bp->b_flags & B_ERROR) {
-                       error = u.u_error;              /* XXX */
-                       u.u_error = 0;
-               }
-bad:
-               brelse(bp);
+               fop = (struct format_op *)data;
+               aiov.iov_base = fop->df_buf;
+               aiov.iov_len = fop->df_count;
+               auio.uio_iov = &aiov;
+               auio.uio_iovcnt = 1;
+               auio.uio_resid = fop->df_count;
+               auio.uio_segflg = UIO_USERSPACE;
+               auio.uio_offset = fop->df_startblk * lp->d_secsize;
+               dk->dk_operrsta = fop->dk_operrsta;
+               dk->dk_ecode = fop->dk_ecode;
+               /*
+                * Don't return errors, as the format op won't get copied
+                * out if we return nonzero.  Callers must check the returned
+                * count.
+                */
+               (void) physio(vdformat, (struct buf *)NULL, dev,
+                   (cmd == DIOCWFORMAT ? B_WRITE : B_READ), minphys, &auio);
+               fop->df_count -= auio.uio_resid;
+               fop->dk_operrsta = dk->dk_operrsta;
+               fop->dk_ecode = dk->dk_ecode;
                break;
                break;
-       }
+           }
 
        default:
                error = ENOTTY;
                break;
        }
 
        default:
                error = ENOTTY;
                break;
        }
-       return (0);
+       return (error);
+}
+
+vdformat(bp)
+       struct buf *bp;
+{
+       bp->b_flags |= B_FORMAT;
+       vdstrategy(bp);
 }
 
 /*
 }
 
 /*
@@ -872,7 +1003,8 @@ vdwatch()
 {
        register struct vdsoftc *vd;
        register struct vba_ctlr *vm;
 {
        register struct vdsoftc *vd;
        register struct vba_ctlr *vm;
-       register int ctlr, unit;
+       register int ctlr;
+       int s;
 
        timeout(vdwatch, (caddr_t)0, hz);
        for (ctlr = 0; ctlr < NVD; ctlr++) {
 
        timeout(vdwatch, (caddr_t)0, hz);
        for (ctlr = 0; ctlr < NVD; ctlr++) {
@@ -880,11 +1012,15 @@ vdwatch()
                if (vm == 0 || vm->um_alive == 0)
                        continue;
                vd = &vdsoftc[ctlr];
                if (vm == 0 || vm->um_alive == 0)
                        continue;
                vd = &vdsoftc[ctlr];
-               if (vm->um_tab.b_active && vd->vd_wticks++ >= 20) {
-                       vd->vd_wticks = 0;
+               s = spl7();
+               if (vm->um_tab.b_active && vd->vd_wticks++ >= VDMAXTIME) {
                        printf("vd%d: lost interrupt\n", ctlr);
                        printf("vd%d: lost interrupt\n", ctlr);
-                       /* abort pending dcb's and restart controller */
+#ifdef maybe
+                       VDABORT((struct vddevice *)vm->um_addr, vd->vd_type);
+#endif
+                       vdintr(ctlr);
                }
                }
+               splx(s);
        }
 }
 
        }
 }
 
@@ -908,13 +1044,14 @@ vddump(dev)
        if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
                return (ENXIO);
        dk = &dksoftc[unit];
        if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
                return (ENXIO);
        dk = &dksoftc[unit];
-       if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
+       if (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
+           vdinit(vdminor(unit, 0), 0) != 0)
                return (ENXIO);
        lp = &dklabel[unit];
        part = vdpart(dev);
        if (part >= lp->d_npartitions)
                return (ENXIO);
                return (ENXIO);
        lp = &dklabel[unit];
        part = vdpart(dev);
        if (part >= lp->d_npartitions)
                return (ENXIO);
-       vm = vdminfo[vi->ui_ctlr];
+       vm = vi->ui_mi;
        vdreset_ctlr(vm);
        if (dumplo < 0)
                return (EINVAL);
        vdreset_ctlr(vm);
        if (dumplo < 0)
                return (EINVAL);
@@ -928,7 +1065,7 @@ vddump(dev)
        vd = &vdsoftc[vm->um_ctlr];
        vd->vd_dcb.intflg = DCBINT_NONE;
        vd->vd_dcb.opcode = VDOP_WD;
        vd = &vdsoftc[vm->um_ctlr];
        vd->vd_dcb.intflg = DCBINT_NONE;
        vd->vd_dcb.opcode = VDOP_WD;
-       vd->vd_dcb.devselect = vi->ui_slave;
+       vd->vd_dcb.devselect = dk->dk_dcb.devselect;
        vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        while (num > 0) {
                int nsec, cn, sn, tn;
        vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        while (num > 0) {
                int nsec, cn, sn, tn;
@@ -1019,21 +1156,22 @@ vdreset_drive(vi)
        register struct disklabel *lp = &dklabel[vi->ui_unit];
        struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
        struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
        register struct disklabel *lp = &dklabel[vi->ui_unit];
        struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
        struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
-       struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
+       register struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
+       register struct dksoftc *dk = &dksoftc[vi->ui_unit];
 
 top:
        vd->vd_dcb.opcode = VDOP_CONFIG;                /* command */
        vd->vd_dcb.intflg = DCBINT_NONE;
        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        vd->vd_dcb.operrsta = 0;
 
 top:
        vd->vd_dcb.opcode = VDOP_CONFIG;                /* command */
        vd->vd_dcb.intflg = DCBINT_NONE;
        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        vd->vd_dcb.operrsta = 0;
-       vd->vd_dcb.devselect = vi->ui_slave;
+       vd->vd_dcb.devselect = vi->ui_slave | lp->d_devflags;
        vd->vd_dcb.trail.rstrail.ncyl = lp->d_ncylinders;
        vd->vd_dcb.trail.rstrail.nsurfaces = lp->d_ntracks;
        if (vd->vd_type == VDTYPE_SMDE) {
                vd->vd_dcb.trailcnt = sizeof (struct treset) / sizeof (long);
                vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
                vd->vd_dcb.trail.rstrail.slip_sec = lp->d_sparespertrack;
        vd->vd_dcb.trail.rstrail.ncyl = lp->d_ncylinders;
        vd->vd_dcb.trail.rstrail.nsurfaces = lp->d_ntracks;
        if (vd->vd_type == VDTYPE_SMDE) {
                vd->vd_dcb.trailcnt = sizeof (struct treset) / sizeof (long);
                vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
                vd->vd_dcb.trail.rstrail.slip_sec = lp->d_sparespertrack;
-               vd->vd_dcb.trail.rstrail.recovery = 0x18f;
+               vd->vd_dcb.trail.rstrail.recovery = VDRF_NORMAL;
        } else
                vd->vd_dcb.trailcnt = 2;                /* XXX */
        vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        } else
                vd->vd_dcb.trailcnt = 2;                /* XXX */
        vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
@@ -1044,24 +1182,36 @@ top:
                return (0);
        }
        if (vd->vd_dcb.operrsta & VDERR_HARD) {
                return (0);
        }
        if (vd->vd_dcb.operrsta & VDERR_HARD) {
-               if (vd->vd_type == VDTYPE_SMDE &&
-                   (vdaddr->vdstatus[vi->ui_slave]&STA_US) == 0)
-                       return (0);
+               if (vd->vd_type == VDTYPE_SMDE) {
+                       if (lp->d_devflags == 0) {
+                               lp->d_devflags = VD_ESDI;
+                               goto top;
+                       }
+#ifdef notdef
+                       /* this doesn't work, STA_US isn't set(?) */
+                       if ((vdaddr->vdstatus[vi->ui_slave] & STA_US) == 0)
+                               return (0);
+#endif
+               }
                if ((vd->vd_dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0)
                if ((vd->vd_dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0)
-                       printf("dk%d: config error\n", vi->ui_unit);
-               else if ((vd->vd_flags&VD_STARTED) == 0) {
+                       printf("dk%d: config error %b ecode %x\n", vi->ui_unit,
+                          vd->vd_dcb.operrsta, VDERRBITS,
+                          (u_char) vd->vd_dcb.err_code);
+               else if ((vd->vd_flags & VD_STARTED) == 0) {
                        int started;
 
                        int started;
 
-                       printf("vd%d: starting drives, wait ... ", vm->um_ctlr);
+                       printf(" starting drives, wait ... ");
                        vd->vd_flags |= VD_STARTED;
                        started = (vdcmd(vm, VDOP_START, 10) == 1);
                        DELAY(62000000);
                        vd->vd_flags |= VD_STARTED;
                        started = (vdcmd(vm, VDOP_START, 10) == 1);
                        DELAY(62000000);
-                       printf("\n");
+                       printf("done");
+                       lp->d_devflags = 0;
                        if (started)
                                goto top;
                }
                return (0);
        }
                        if (started)
                                goto top;
                }
                return (0);
        }
+       dk->dk_dcb.devselect |= lp->d_devflags;
        return (1);
 }
 
        return (1);
 }
 
@@ -1108,7 +1258,6 @@ vdpoll(vm, t)
                if (--t <= 0) {
                        printf("vd%d: controller timeout", vm->um_ctlr);
                        VDABORT(vdaddr, vd->vd_type);
                if (--t <= 0) {
                        printf("vd%d: controller timeout", vm->um_ctlr);
                        VDABORT(vdaddr, vd->vd_type);
-                       DELAY(30000);
                        return (0);
                }
                DELAY(1000);
                        return (0);
                }
                DELAY(1000);
@@ -1118,7 +1267,8 @@ vdpoll(vm, t)
                        DELAY(50);
                        uncache(&vdaddr->vdcsr);
                } while (vdaddr->vdcsr & CS_GO);
                        DELAY(50);
                        uncache(&vdaddr->vdcsr);
                } while (vdaddr->vdcsr & CS_GO);
-               DELAY(300);
+               DELAY(300);
+               uncache(&vd->vd_dcb.err_code);
        }
        DELAY(200);
        uncache(&vd->vd_dcb.operrsta);
        }
        DELAY(200);
        uncache(&vd->vd_dcb.operrsta);
@@ -1130,43 +1280,57 @@ struct  vdst {
        int     nsec;           /* sectors/track */
        int     ntrack;         /* tracks/cylinder */
        int     ncyl;           /* cylinders */
        int     nsec;           /* sectors/track */
        int     ntrack;         /* tracks/cylinder */
        int     ncyl;           /* cylinders */
+       int     secsize;        /* sector size */
        char    *name;          /* type name */
        struct {
                int     off;    /* partition offset in sectors */
                int     size;   /* partition size in sectors */
        } parts[8];
 } vdst[] = {
        char    *name;          /* type name */
        struct {
                int     off;    /* partition offset in sectors */
                int     size;   /* partition size in sectors */
        } parts[8];
 } vdst[] = {
-       { 48, 24, 711, "xsd",
-               {0,      30528},        /* a cyl   0 - 52 */
-               {30528,  30528},        /* b cyl  53 - 105 */
-               {61056,  345600},       /* c cyl 106 - 705 */
-               {118656, 288000},       /* d cyl 206 - 705 */
-               {176256, 230400},       /* e cyl 306 - 705 */
-               {233856, 172800},       /* f cyl 406 - 705 */
-               {291456, 115200},       /* g cyl 506 - 705 */
-               {349056, 57600}         /* h cyl 606 - 705 */
+       { 66, 23, 850, 512, "NEC 800",
+               {0,      1290300},      /* a cyl   0 - 849 */
+       },
+       { 64, 20, 842, 512, "2361a",
+               {0,      61440},        /* a cyl   0 - 47 */
+               {61440,  67840},        /* b cyl  48 - 100 */
+               {129280, 942080},       /* c cyl 101 - 836 */
+               {0,      1071360},      /* d cyl   0 - 836 */
+               {449280, 311040},       /* e cyl 351 - 593 */
+               {760320, 311040},       /* f cyl 594 - 836 */
+               {449280, 622080},       /* g cyl 351 - 836 */
+               {129280, 320000}        /* h cyl 101 - 350 */
+       },
+       { 48, 24, 711, 512, "xsd",
+               {0,      61056},        /* a cyl   0 - 52 */
+               {61056,  61056},        /* b cyl  53 - 105 */
+               {122112, 691200},       /* c cyl 106 - 705 */
+               {237312, 576000},       /* d cyl 206 - 705 */
+               {352512, 460800},       /* e cyl 306 - 705 */
+               {467712, 345600},       /* f cyl 406 - 705 */
+               {582912, 230400},       /* g cyl 506 - 705 */
+               {698112, 115200}        /* h cyl 606 - 705 */
        },
        },
-       { 44, 20, 842, "egl",
+       { 44, 20, 842, 512, "eagle",
                {0,      52800},        /* egl0a cyl   0 - 59 */
                {52800,  66000},        /* egl0b cyl  60 - 134 */
                {118800, 617760},       /* egl0c cyl 135 - 836 */
                {736560, 4400},         /* egl0d cyl 837 - 841 */
                {0,      52800},        /* egl0a cyl   0 - 59 */
                {52800,  66000},        /* egl0b cyl  60 - 134 */
                {118800, 617760},       /* egl0c cyl 135 - 836 */
                {736560, 4400},         /* egl0d cyl 837 - 841 */
-               {0,      736560},       /* egl0e cyl 0 - 836 */
-               {0,      740960},       /* egl0f cyl 0 - 841 */
+               {0,      736560},       /* egl0e cyl   0 - 836 */
+               {0,      740960},       /* egl0f cyl   0 - 841 */
                {118800, 310640},       /* egl0g cyl 135 - 487 */
                {429440, 307120}        /* egl0h cyl 488 - 836 */
        },
                {118800, 310640},       /* egl0g cyl 135 - 487 */
                {429440, 307120}        /* egl0h cyl 488 - 836 */
        },
-       { 64, 10, 823, "fuj",
-               {0,      19200},        /* fuj0a cyl   0 - 59 */
-               {19200,  24000},        /* fuj0b cyl  60 - 134 */
-               {43200,  218560},       /* fuj0c cyl 135 - 817 */
-               {79680,  182080},       /* fuj0d cyl 249 - 817 */
-               {116160, 145600},       /* fuj0e cyl 363 - 817 */
-               {152640, 109120},       /* fuj0f cyl 477 - 817 */
-               {189120, 72640},        /* fuj0g cyl 591 - 817 */
-               {225600, 36160}         /* fug0h cyl 705 - 817 */
+       { 64, 10, 823, 512, "fuj",
+               {0,      38400},        /* fuj0a cyl   0 - 59 */
+               {38400,  48000},        /* fuj0b cyl  60 - 134 */
+               {86400,  437120},       /* fuj0c cyl 135 - 817 */
+               {159360, 364160},       /* fuj0d cyl 249 - 817 */
+               {232320, 291200},       /* fuj0e cyl 363 - 817 */
+               {305280, 218240},       /* fuj0f cyl 477 - 817 */
+               {378240, 145280},       /* fuj0g cyl 591 - 817 */
+               {451200, 72320}         /* fug0h cyl 705 - 817 */
        },
        },
-       { 32, 24, 711, "xfd",
+       { 32, 24, 711, 512, "xfd",
                { 0,     40704 },       /* a cyl   0 - 52 */
                { 40704, 40704 },       /* b cyl  53 - 105 */
                { 81408, 460800 },      /* c cyl 106 - 705 */
                { 0,     40704 },       /* a cyl   0 - 52 */
                { 40704, 40704 },       /* b cyl  53 - 105 */
                { 81408, 460800 },      /* c cyl 106 - 705 */
@@ -1176,17 +1340,29 @@ struct  vdst {
                { 81408, 230400 },      /* g cyl 106 - 405 (1/2 of c) */
                { 311808,230400 }       /* h cyl 406 - 705 (1/2 of c) */
        },
                { 81408, 230400 },      /* g cyl 106 - 405 (1/2 of c) */
                { 311808,230400 }       /* h cyl 406 - 705 (1/2 of c) */
        },
-       { 32, 19, 823, "smd",
-               {0,      20064},        /* a cyl   0-65 */
-               {20064, 13680},         /* b cyl  66-110 */
-               {33744, 214928},        /* c cyl 111-817 */
-               {69616,  179056},       /* d cyl 229 - 817 */
-               {105488, 143184},       /* e cyl 347 - 817 */
-               {141360, 107312},       /* f cyl 465 - 817 */
-               {177232, 71440},        /* g cyl 583 - 817 */
-               {213104, 35568}         /* h cyl 701 - 817 */
+       { 32, 19, 823, 512, "smd",
+               {0,      40128},        /* a cyl   0-65 */
+               {40128,  27360},        /* b cyl  66-110 */
+               {67488,  429856},       /* c cyl 111-817 */
+               {139232, 358112},       /* d cyl 229 - 817 */
+               {210976, 286368},       /* e cyl 347 - 817 */
+               {282720, 214624},       /* f cyl 465 - 817 */
+               {354464, 142880},       /* g cyl 583 - 817 */
+               {426208, 71136}         /* h cyl 701 - 817 */
        },
        },
-       { 32, 10, 823, "fsd",
+       { 18, 15, 1224, 1024, "mxd",
+               {0,      21600},        /* a cyl   0-79 */
+               {21600,  22410},        /* b cyl  80-162 */
+               {44010,  285120},       /* c cyl 163-1217 */
+#ifdef notyet
+               {x, 237600},    /* d cyl y - 1217 */
+               {x, 190080},    /* e cyl y - 1217 */
+               {x, 142560},    /* f cyl y - 1217 */
+               {x, 95040},     /* g cyl y - 1217 */
+               {x, 47520}              /* h cyl 701 - 817 */
+#endif
+       },
+       { 32, 10, 823, 512, "fsd",
                {0,      19200},        /* a cyl   0 -  59 */
                {19200,  24000},        /* b cyl  60 - 134 */
                {43200,  218560},       /* c cyl 135 - 817 */
                {0,      19200},        /* a cyl   0 -  59 */
                {19200,  24000},        /* b cyl  60 - 134 */
                {43200,  218560},       /* c cyl 135 - 817 */
@@ -1206,7 +1382,7 @@ vdmaptype(vi, lp)
 {
        register struct vdsoftc *vd;
        register struct vdst *p;
 {
        register struct vdsoftc *vd;
        register struct vdst *p;
-       struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
+       struct vba_ctlr *vm = vi->ui_mi;
        int i;
 
        vd = &vdsoftc[vi->ui_ctlr];
        int i;
 
        vd = &vdsoftc[vi->ui_ctlr];
@@ -1216,16 +1392,17 @@ vdmaptype(vi, lp)
                lp->d_nsectors = p->nsec;
                lp->d_ntracks = p->ntrack;
                lp->d_ncylinders = p->ncyl;
                lp->d_nsectors = p->nsec;
                lp->d_ntracks = p->ntrack;
                lp->d_ncylinders = p->ncyl;
+               lp->d_secsize = p->secsize;
                if (!vdreset_drive(vi))
                        return (0);
                vd->vd_dcb.opcode = VDOP_RD;
                vd->vd_dcb.intflg = DCBINT_NONE;
                vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
                if (!vdreset_drive(vi))
                        return (0);
                vd->vd_dcb.opcode = VDOP_RD;
                vd->vd_dcb.intflg = DCBINT_NONE;
                vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
-               vd->vd_dcb.devselect = vi->ui_slave;
+               vd->vd_dcb.devselect = dksoftc[vi->ui_unit].dk_dcb.devselect;
                vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
                vd->vd_dcb.trail.rwtrail.memadr =
                    vtoph((struct proc *)0, (unsigned)vd->vd_rbuf.vb_rawbuf);
                vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
                vd->vd_dcb.trail.rwtrail.memadr =
                    vtoph((struct proc *)0, (unsigned)vd->vd_rbuf.vb_rawbuf);
-               vd->vd_dcb.trail.rwtrail.wcount = 512 / sizeof(short);
+               vd->vd_dcb.trail.rwtrail.wcount = lp->d_secsize / sizeof(short);
                vd->vd_dcb.operrsta = 0;
                vd->vd_dcb.trail.rwtrail.disk.cylinder = p->ncyl - 2;
                vd->vd_dcb.trail.rwtrail.disk.track = p->ntrack - 1;
                vd->vd_dcb.operrsta = 0;
                vd->vd_dcb.trail.rwtrail.disk.cylinder = p->ncyl - 2;
                vd->vd_dcb.trail.rwtrail.disk.track = p->ntrack - 1;
@@ -1238,10 +1415,9 @@ vdmaptype(vi, lp)
                if ((vd->vd_dcb.operrsta & VDERR_HARD) == 0)
                        break;
        }
                if ((vd->vd_dcb.operrsta & VDERR_HARD) == 0)
                        break;
        }
-       if (p >= &vdst[NVDST]) {
-               printf("dk%d: unknown drive type\n", vi->ui_unit);
+       if (p >= &vdst[NVDST])
                return (0);
                return (0);
-       }
+
        for (i = 0; i < 8; i++) {
                lp->d_partitions[i].p_offset = p->parts[i].off;
                lp->d_partitions[i].p_size = p->parts[i].size;
        for (i = 0; i < 8; i++) {
                lp->d_partitions[i].p_offset = p->parts[i].off;
                lp->d_partitions[i].p_size = p->parts[i].size;
@@ -1249,7 +1425,6 @@ vdmaptype(vi, lp)
        lp->d_npartitions = 8;
        lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        lp->d_rpm = 3600;
        lp->d_npartitions = 8;
        lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        lp->d_rpm = 3600;
-       lp->d_secsize = 512;
        bcopy(p->name, lp->d_typename, 4);
        return (1);
 }
        bcopy(p->name, lp->d_typename, 4);
        return (1);
 }