changes for var. length sockaddrs; new routing; mv common ether input
[unix-history] / usr / src / sys / tahoe / vba / vd.c
index 1e10458..31f9597 100644 (file)
@@ -1,4 +1,24 @@
-/*     vd.c    1.16    87/03/01        */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Computer Consoles Inc.
+ *
+ * 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.9 (Berkeley) %G%
+ */
 
 #include "dk.h"
 #if NVD > 0
 
 #include "dk.h"
 #if NVD > 0
@@ -22,6 +42,7 @@
 #include "syslog.h"
 #include "kernel.h"
 #include "ioctl.h"
 #include "syslog.h"
 #include "kernel.h"
 #include "ioctl.h"
+#include "stat.h"
 
 #include "../tahoe/cpu.h"
 #include "../tahoe/mtpr.h"
 
 #include "../tahoe/cpu.h"
 #include "../tahoe/mtpr.h"
 #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
-
-#define        VDMAXIO         (MAXBPTE*NBPG)
+#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)
 
 struct vba_ctlr *vdminfo[NVD];
 struct  vba_device *vddinfo[NDK];
 
 struct vba_ctlr *vdminfo[NVD];
 struct  vba_device *vddinfo[NDK];
-int    vdprobe(), vdslave(), vdattach(), vddgo();
-long   vdaddr[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
+int    vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();
+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.
@@ -53,32 +75,42 @@ struct vdsoftc {
 #define        VD_INIT         0x1     /* controller initialized */
 #define        VD_STARTED      0x2     /* start command issued */
 #define        VD_DOSEEKS      0x4     /* should overlap seeks */
 #define        VD_INIT         0x1     /* controller initialized */
 #define        VD_STARTED      0x2     /* start command issued */
 #define        VD_DOSEEKS      0x4     /* should overlap seeks */
+#define        VD_SCATGATH     0x8     /* can do scatter-gather commands (correctly) */
+#define        VD_LOCKED       0x10    /* locked for direct controller access */
+#define        VD_WAIT         0x20    /* someone needs direct controller access */
        u_short vd_type;        /* controller type */
        u_short vd_wticks;      /* timeout */
        struct  mdcb vd_mdcb;   /* master command block */
        u_long  vd_mdcbphys;    /* physical address of vd_mdcb */
        struct  dcb vd_dcb;     /* i/o command block */
        u_long  vd_dcbphys;     /* physical address of vd_dcb */
        u_short vd_type;        /* controller type */
        u_short vd_wticks;      /* timeout */
        struct  mdcb vd_mdcb;   /* master command block */
        u_long  vd_mdcbphys;    /* physical address of vd_mdcb */
        struct  dcb vd_dcb;     /* i/o command block */
        u_long  vd_dcbphys;     /* physical address of vd_dcb */
-       struct  pte *vd_map;    /* i/o page map */
-       caddr_t vd_utl;         /* mapped i/o space */
-       caddr_t vd_rawbuf;      /* buffer for raw+swap i/o */
+       struct  vb_buf vd_rbuf; /* vba resources */
 } vdsoftc[NVD];
 
 } 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_openpart;    /* units open on this drive */
+       int     dk_state;       /* open fsm */
+#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 */
        u_int   dk_curcyl;      /* last selected cylinder */
-       struct  dcb dk_dcb;     /* seek command block */
+       struct  skdcb dk_dcb;   /* seek command block */
        u_long  dk_dcbphys;     /* physical address of dk_dcb */
        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 */
@@ -87,7 +119,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 */
 
@@ -133,7 +164,7 @@ vdprobe(reg, vm)
                vdaddr->vdtcf_dcb = AM_ENPDA;
                vdaddr->vdtcf_trail = AM_ENPDA;
                vdaddr->vdtcf_data = AM_ENPDA;
                vdaddr->vdtcf_dcb = AM_ENPDA;
                vdaddr->vdtcf_trail = AM_ENPDA;
                vdaddr->vdtcf_data = AM_ENPDA;
-               vdaddr->vdccf = CCF_SEN | CCF_DER | CCF_STS |
+               vdaddr->vdccf = CCF_SEN | CCF_DIU | CCF_STS |
                    XMD_32BIT | BSZ_16WRD |
                    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
        }
                    XMD_32BIT | BSZ_16WRD |
                    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
        }
@@ -141,18 +172,29 @@ vdprobe(reg, vm)
        vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);
        vm->um_addr = reg;              /* XXX */
        s = spl7();
        vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);
        vm->um_addr = reg;              /* XXX */
        s = spl7();
-       if (!vdcmd(vm, VDOP_INIT, 10) || !vdcmd(vm, VDOP_DIAG, 10)) {
+       if (!vdcmd(vm, VDOP_INIT, 10, 0) || !vdcmd(vm, VDOP_DIAG, 10, 0)) {
                printf("vd%d: %s cmd failed\n", vm->um_ctlr,
                    vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
                splx(s);
                return (0);
        }
                printf("vd%d: %s cmd failed\n", vm->um_ctlr,
                    vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
                splx(s);
                return (0);
        }
+       if (vd->vd_type == VDTYPE_SMDE) {
+               vd->vd_dcb.trail.idtrail.date = 0;
+               if (vdcmd(vm, VDOP_IDENT, 10, 0)) {
+                       uncache(&vd->vd_dcb.trail.idtrail.date);
+                       if (vd->vd_dcb.trail.idtrail.date != 0)
+                               vd->vd_flags |= VD_SCATGATH;
+               }
+       }
        splx(s);
        /*
         * Allocate page tables and i/o buffer.
         */
        splx(s);
        /*
         * Allocate page tables and i/o buffer.
         */
-       vbmapalloc(btoc(VDMAXIO)+1, &vd->vd_map, &vd->vd_utl);
-       vd->vd_rawbuf = calloc(VDMAXIO);
+       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));
 }
@@ -165,16 +207,29 @@ 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) {
-               printf("vd%d: %s controller\n", vi->ui_ctlr,
+               printf("vd%d: %s controller", vi->ui_ctlr,
                    vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");
                    vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");
+               if (vd->vd_flags & VD_SCATGATH) {
+                       char rev[5];
+
+                       bcopy((caddr_t)&vd->vd_dcb.trail.idtrail.rev, rev,
+                           sizeof(vd->vd_dcb.trail.idtrail.rev));
+                       printf(" firmware rev %s (%d-%d-%d)", rev,
+                           (vd->vd_dcb.trail.idtrail.date >> 8) & 0xff,
+                           vd->vd_dcb.trail.idtrail.date & 0xff,
+                           (vd->vd_dcb.trail.idtrail.date >> 16) & 0xffff);
+               }
+               printf("\n");
                vd->vd_flags |= VD_INIT;
        }
 
                vd->vd_flags |= VD_INIT;
        }
 
@@ -184,23 +239,40 @@ 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;
+       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_rpm = 3600;
+       lp->d_npartitions = 1;
+       lp->d_partitions[0].p_offset = 0;
+       lp->d_partitions[0].p_size = LABELSECTOR + 1;
+
+       /*
+        * Initialize invariant portion of
+        * dcb used for overlapped seeks.
+        */
+       dk->dk_dcb.opcode = VDOP_SEEK;
+       dk->dk_dcb.intflg = DCBINT_NONE | DCBINT_PBA;
+       dk->dk_dcb.devselect = vi->ui_slave;
+       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));
 }
 
        return (vdreset_drive(vi));
 }
 
-/*
- * Read pack label.
- */
 vdattach(vi)
        register struct vba_device *vi;
 {
        register int unit = vi->ui_unit;
 vdattach(vi)
        register struct vba_device *vi;
 {
        register int unit = vi->ui_unit;
-       register struct dksoftc *dk = &dksoftc[unit];
-       register struct disklabel *lp;
+       register struct disklabel *lp = &dklabel[unit];
 
        /*
         * Try to initialize device and read pack label.
 
        /*
         * Try to initialize device and read pack label.
@@ -209,19 +281,10 @@ vdattach(vi)
                printf(": unknown drive type");
                return;
        }
                printf(": unknown drive type");
                return;
        }
-       /*
-        * Initialize invariant portion of
-        * dcb used for overlapped seeks.
-        */
-       dk->dk_dcb.opcode = VDOP_SEEK;
-       dk->dk_dcb.intflg = DCBINT_NONE | DCBINT_PBA;
-       dk->dk_dcb.devselect = vi->ui_slave;
-       dk->dk_dcb.trailcnt = sizeof (trseek) / sizeof (long);
-       dk->dk_dcb.trail.sktrail.skaddr.sector = 0;
-       dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);
-       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))
         */
@@ -233,17 +296,16 @@ vdattach(vi)
 #endif
 }
 
 #endif
 }
 
-/*ARGSUSED*/
-vdopen(dev, flags)
+vdopen(dev, flags, fmt)
        dev_t dev;
        dev_t dev;
-       int flags;
+       int flags, fmt;
 {
        register unit = vdunit(dev);
        register struct disklabel *lp;
        register struct dksoftc *dk;
        register struct partition *pp;
        struct vba_device *vi;
 {
        register unit = vdunit(dev);
        register struct disklabel *lp;
        register struct dksoftc *dk;
        register struct partition *pp;
        struct vba_device *vi;
-       int s, error, part = vdpart(dev);
+       int s, error, part = vdpart(dev), mask = 1 << part;
        daddr_t start, end;
 
        if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
        daddr_t start, end;
 
        if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
@@ -269,9 +331,8 @@ vdopen(dev, flags)
         * 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;
@@ -291,18 +352,37 @@ vdopen(dev, flags)
        }
        if (part >= lp->d_npartitions)
                return (ENXIO);
        }
        if (part >= lp->d_npartitions)
                return (ENXIO);
-       dk->dk_openpart |= 1 << part;
+       dk->dk_openpart |= mask;
+       switch (fmt) {
+       case S_IFCHR:
+               dk->dk_copenpart |= mask;
+               break;
+       case S_IFBLK:
+               dk->dk_bopenpart |= mask;
+               break;
+       }
        return (0);
 }
 
        return (0);
 }
 
-vdclose(dev, flags)
+/* ARGSUSED */
+vdclose(dev, flags, fmt)
        dev_t dev;
        dev_t dev;
-       int flags;
+       int flags, fmt;
 {
        register int unit = vdunit(dev);
        register struct dksoftc *dk = &dksoftc[unit];
 {
        register int unit = vdunit(dev);
        register struct dksoftc *dk = &dksoftc[unit];
+       int part = vdpart(dev), mask = 1 << part;
 
 
-       dk->dk_openpart &= ~(1 << vdpart(dev));
+       switch (fmt) {
+       case S_IFCHR:
+               dk->dk_copenpart &= ~mask;
+               break;
+       case S_IFBLK:
+               dk->dk_bopenpart &= ~mask;
+               break;
+       }
+       if (((dk->dk_copenpart | dk->dk_bopenpart) & mask) == 0)
+               dk->dk_openpart &= ~mask;
        /*
         * Should wait for i/o to complete on this partition
         * even if others are open, but wait for work on blkflush().
        /*
         * Should wait for i/o to complete on this partition
         * even if others are open, but wait for work on blkflush().
@@ -313,89 +393,83 @@ vdclose(dev, flags)
                        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);
 }
 
 vdinit(dev, flags)
        dev_t dev;
        int flags;
 {
 }
 
 vdinit(dev, flags)
        dev_t dev;
        int flags;
 {
-       register struct buf *bp = NULL;
        register struct disklabel *lp;
        register struct dksoftc *dk;
        struct vba_device *vi;
        register struct disklabel *lp;
        register struct dksoftc *dk;
        struct vba_device *vi;
-       struct disklabel *dlp;
        int unit = vdunit(dev), error = 0;
        int unit = vdunit(dev), error = 0;
+       char *msg, *readdisklabel();
        extern int cold;
 
        dk = &dksoftc[unit];
        if (flags & O_NDELAY) {
                dk->dk_state = OPENRAW;
        extern int cold;
 
        dk = &dksoftc[unit];
        if (flags & O_NDELAY) {
                dk->dk_state = OPENRAW;
-               goto done;
+               return (0);
        }
        }
-
-       /*
-        * Initialize portion of the label
-        * not set up in the slave routine.
-        */
        dk->dk_state = RDLABEL;
        lp = &dklabel[unit];
        dk->dk_state = RDLABEL;
        lp = &dklabel[unit];
-       lp->d_secperunit = 0x1fffffff;
-       lp->d_npartitions = 1;
-       lp->d_partitions[0].p_size = 0x1fffffff;
-       lp->d_partitions[0].p_offset = 0;
-
-       bp = geteblk(DEV_BSIZE);                /* max sector size */
-       bp->b_dev = dev;
-       bp->b_blkno = LABELSECTOR;
-       bp->b_bcount = DEV_BSIZE;
-       bp->b_flags = B_BUSY | B_READ;
-       bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
-       vdstrategy(bp);
-       biowait(bp);
-       if (bp->b_flags & B_ERROR) {
-               error = u.u_error;              /* XXX */
-               u.u_error = 0;
-               dk->dk_state = CLOSED;
-               goto done;
-       }
        vi = vddinfo[unit];
        vi = vddinfo[unit];
-       dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
-       if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
-           dkcksum(dlp) == 0) {
-               *lp = *dlp;
+       if (msg = readdisklabel(dev, vdstrategy, lp)) {
+               if (cold) {
+                       printf(": %s", msg);
+                       dk->dk_state = CLOSED;
+               } else {
+                       log(LOG_ERR, "dk%d: %s\n", unit, msg);
+                       dk->dk_state = OPENRAW;
+               }
+#ifdef COMPAT_42
+               vdlock(vi->ui_ctlr);
+               if (vdmaptype(vi, lp))
+                       dk->dk_state = OPEN;
+               vdunlock(vi->ui_ctlr);
+#endif
+       } else {
                /*
                 * Now that we have the label, configure
                 * the correct drive parameters.
                 */
                /*
                 * Now that we have the label, configure
                 * the correct drive parameters.
                 */
-               if (!vdreset_drive(vi))
-                       dk->dk_state = CLOSED;
-               else
+               vdlock(vi->ui_ctlr);
+               if (vdreset_drive(vi))
                        dk->dk_state = OPEN;
                        dk->dk_state = OPEN;
-       } else {
-               if (cold)
-                       printf(": no disk label");
-               else
-                       log(LOG_ERR, "dk%d: no disk label\n", vi->ui_unit);
-#ifdef COMPAT_42
-               if (!vdmaptype(vi, lp)) {
-                       error = ENXIO;
+               else {
                        dk->dk_state = CLOSED;
                        dk->dk_state = CLOSED;
-               } else
-                       dk->dk_state = OPEN;
-#else
-               dk->dk_state = OPENRAW;
-#endif
-       }
-done:
-       if (bp) {
-               bp->b_flags = B_INVAL | B_AGE;
-               brelse(bp);
+                       error = ENXIO;
+               }
+               vdunlock(vi->ui_ctlr);
        }
        }
+#ifndef 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;
@@ -415,10 +489,8 @@ vdstrategy(bp)
        daddr_t sz, maxsz;
        int part, s;
 
        daddr_t sz, maxsz;
        int part, s;
 
-       sz = bp->b_bcount;
-       sz = (sz + DEV_BSIZE - 1) >> DEV_BSHIFT;
        unit = vdunit(bp->b_dev);
        unit = vdunit(bp->b_dev);
-       if (unit > NDK) {
+       if (unit >= NDK) {
                bp->b_error = ENXIO;
                goto bad;
        }
                bp->b_error = ENXIO;
                goto bad;
        }
@@ -431,19 +503,36 @@ vdstrategy(bp)
        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;
        maxsz = lp->d_partitions[part].p_size;
+#ifndef SECSIZE
+       sn = bp->b_blkno << dk->dk_bshift;
+#else SECSIZE
        sn = bp->b_blkno;
        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;
                        goto done;
                }
        if (sn < 0 || sn + sz > maxsz) {
                if (sn == maxsz) {
                        bp->b_resid = bp->b_bcount;
                        goto done;
                }
-               sz = maxsz - bp->b_blkno;
+               sz = maxsz - sn;
                if (sz <= 0) {
                        bp->b_error = EINVAL;
                        goto bad;
                if (sz <= 0) {
                        bp->b_error = EINVAL;
                        goto bad;
@@ -451,8 +540,11 @@ vdstrategy(bp)
                bp->b_bcount = sz * lp->d_secsize;
        }
        bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
                bp->b_bcount = sz * lp->d_secsize;
        }
        bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
+#ifdef SECSIZE
+if (bp->b_blksize != lp->d_secsize && (bp->b_flags & B_PGIN) == 0)
+panic("vdstrat blksize");
+#endif SECSIZE
 q:
 q:
-       vbasetup(bp, lp->d_secsize);
        s = spl7();
        dp = &dkutab[vi->ui_unit];
        disksort(dp, bp);
        s = spl7();
        dp = &dkutab[vi->ui_unit];
        disksort(dp, bp);
@@ -530,9 +622,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;
 
@@ -544,7 +634,10 @@ loop:
            (dp = vm->um_tab.b_seekf) == NULL)
                return;
        if ((bp = dp->b_actf) == NULL) {
            (dp = vm->um_tab.b_seekf) == NULL)
                return;
        if ((bp = dp->b_actf) == NULL) {
-               vm->um_tab.b_actf = dp->b_forw;
+               if (dp == vm->um_tab.b_actf)
+                       vm->um_tab.b_actf = dp->b_forw;
+               else
+                       vm->um_tab.b_seekf = dp->b_forw;
                goto loop;
        }
 
                goto loop;
        }
 
@@ -555,7 +648,11 @@ loop:
        vm->um_tab.b_active++;
        vi = vddinfo[vdunit(bp->b_dev)];
        dk = &dksoftc[vi->ui_unit];
        vm->um_tab.b_active++;
        vi = vddinfo[vdunit(bp->b_dev)];
        dk = &dksoftc[vi->ui_unit];
+#ifndef SECSIZE
+       sn = bp->b_blkno << dk->dk_bshift;
+#else SECSIZE
        sn = bp->b_blkno;
        sn = bp->b_blkno;
+#endif SECSIZE
        lp = &dklabel[vi->ui_unit];
        sn %= lp->d_secpercyl;
        tn = sn / lp->d_nsectors;
        lp = &dklabel[vi->ui_unit];
        sn %= lp->d_secpercyl;
        tn = sn / lp->d_nsectors;
@@ -565,21 +662,48 @@ 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.opcode = (bp->b_flags & B_READ) ? VDOP_RD : VDOP_WD;
        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.operrsta = 0;
        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
-       vd->vd_dcb.trailcnt = sizeof (trrw) / sizeof (long);
-       vd->vd_dcb.trail.rwtrail.memadr = (char *)
-           vbastart(bp, vd->vd_rawbuf, (long *)vd->vd_map, vd->vd_utl);
-       vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
        vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
        vd->vd_dcb.trail.rwtrail.disk.track = tn;
        vd->vd_dcb.trail.rwtrail.disk.sector = sn;
        dk->dk_curcyl = bp->b_cylin;
        bp->b_track = 0;                /* init overloaded field */
        vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
        vd->vd_dcb.trail.rwtrail.disk.track = tn;
        vd->vd_dcb.trail.rwtrail.disk.sector = sn;
        dk->dk_curcyl = bp->b_cylin;
        bp->b_track = 0;                /* init overloaded field */
+       vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
+       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;
+       else
+               vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RD : VDOP_WD;
+
+       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;
+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 += vd_sgsetup(bp, &vd->vd_rbuf,
+                   &vd->vd_dcb.trail.sgtrail);
+               break;
+       }
        if (vi->ui_dk >= 0) {
                dk_busy |= 1<<vi->ui_dk;
                dk_xfer[vi->ui_dk]++;
        if (vi->ui_dk >= 0) {
                dk_busy |= 1<<vi->ui_dk;
                dk_xfer[vi->ui_dk]++;
@@ -607,13 +731,7 @@ loop:
                        dk_seek[vi->ui_dk]++;
                dk->dk_dcb.operrsta = 0;
                dk->dk_dcb.trail.sktrail.skaddr.cylinder = bp->b_cylin;
                        dk_seek[vi->ui_dk]++;
                dk->dk_dcb.operrsta = 0;
                dk->dk_dcb.trail.sktrail.skaddr.cylinder = bp->b_cylin;
-#ifdef notdef
-               dk->dk_dcb.trail.sktrail.skaddr.track = bp->b_daddr>>8;
-               dk->dk_dcb.trail.sktrail.skaddr.sector =
-                   bp->b_daddr & 0xff;
-#else
                dk->dk_dcb.trail.sktrail.skaddr.track = bp->b_track;
                dk->dk_dcb.trail.sktrail.skaddr.track = bp->b_track;
-#endif
                *dcbp = (struct dcb *)dk->dk_dcbphys;
                dcbp = &dk->dk_dcb.nxtdcb;
        }
                *dcbp = (struct dcb *)dk->dk_dcbphys;
                dcbp = &dk->dk_dcb.nxtdcb;
        }
@@ -622,9 +740,9 @@ loop:
                vm->um_tab.b_actl->b_forw = vm->um_tab.b_seekf;
        else
                vm->um_tab.b_actf = vm->um_tab.b_seekf;
                vm->um_tab.b_actl->b_forw = vm->um_tab.b_seekf;
        else
                vm->um_tab.b_actf = vm->um_tab.b_seekf;
-       vm->um_tab.b_actl = vm->um_tab.b_seekl;
+       if (vm->um_tab.b_seekf)
+               vm->um_tab.b_actl = vm->um_tab.b_seekl;
        vm->um_tab.b_seekf = 0;
        vm->um_tab.b_seekf = 0;
-       vm->um_tab.b_seekl = 0;
 
        /*
         * Initiate operation.
 
        /*
         * Initiate operation.
@@ -633,6 +751,42 @@ loop:
        VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
 }
 
        VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
 }
 
+/*
+ * Wait for controller to finish current operation
+ * so that direct controller accesses can be done.
+ */
+vdlock(ctlr)
+{
+       register struct vba_ctlr *vm = vdminfo[ctlr];
+       register struct vdsoftc *vd = &vdsoftc[ctlr];
+       int s;
+
+       s = spl7();
+       while (vm->um_tab.b_active || vd->vd_flags & VD_LOCKED) {
+               vd->vd_flags |= VD_WAIT;
+               sleep((caddr_t)vd, PRIBIO);
+       }
+       vd->vd_flags |= VD_LOCKED;
+       splx(s);
+}
+
+/*
+ * Continue normal operations after pausing for 
+ * munging the controller directly.
+ */
+vdunlock(ctlr)
+{
+       register struct vba_ctlr *vm = vdminfo[ctlr];
+       register struct vdsoftc *vd = &vdsoftc[ctlr];
+
+       vd->vd_flags &= ~VD_LOCKED;
+       if (vd->vd_flags & VD_WAIT) {
+               vd->vd_flags &= ~VD_WAIT;
+               wakeup((caddr_t)vd);
+       } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
+               vdstart(vm);
+}
+
 #define        DONTCARE (DCBS_DSE|DCBS_DSL|DCBS_TOP|DCBS_TOM|DCBS_FAIL|DCBS_DONE)
 /*
  * Handle a disk interrupt.
 #define        DONTCARE (DCBS_DSE|DCBS_DSL|DCBS_TOP|DCBS_TOM|DCBS_FAIL|DCBS_DONE)
 /*
  * Handle a disk interrupt.
@@ -645,9 +799,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 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;
@@ -659,57 +813,75 @@ 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 (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);
                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) {
-                               uncache(&vd->vd_dcb.err_code);
-                               printf(" ecode %x", vd->vd_dcb.err_code);
-                       }
+                       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;
                dp->b_actf = bp->av_forw;
                bp->b_resid = 0;
                vm->um_tab.b_actf = dp->b_forw;
                dp->b_active = 0;
                dp->b_errcnt = 0;
                dp->b_actf = bp->av_forw;
                bp->b_resid = 0;
-               vbadone(bp, vd->vd_rawbuf, (long *)vd->vd_map, vd->vd_utl);
+               vbadone(bp, &vd->vd_rbuf);
                biodone(bp);
                /*
                 * If this unit has more work to do,
                biodone(bp);
                /*
                 * If this unit has more work to do,
@@ -717,55 +889,64 @@ 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);
        }
        /*
         * If there are devices ready to
         * transfer, start the controller.
         */
                        wakeup((caddr_t)dk);
        }
        /*
         * If there are devices ready to
         * transfer, start the controller.
         */
-       if (vm->um_tab.b_actf)
+       if (vd->vd_flags & VD_WAIT) {
+               vd->vd_flags &= ~VD_WAIT;
+               wakeup((caddr_t)vd);
+       } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
                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_DCE|DCBS_CCD|DCBS_SOFT|DCBS_ERR)) {
-               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);
-}
-
-vdread(dev, uio)
-       dev_t dev;
-       struct uio *uio;
-{
-       register int unit = vdunit(dev);
-
-       if (unit >= NDK)
-               return (ENXIO);
-       return (physio(vdstrategy, &rdkbuf[unit], dev, B_READ, minphys, uio));
+       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);
 }
 
 }
 
-vdwrite(dev, uio)
-       dev_t dev;
-       struct uio *uio;
+vdsofterr(bp, dcb)
+       register struct buf *bp;
+       register struct dcb *dcb;
 {
 {
-       register int unit = vdunit(dev);
-
-       if (unit >= NDK)
-               return (ENXIO);
-       return (physio(vdstrategy, &rdkbuf[unit], dev, B_WRITE, minphys, uio));
+       int unit = vdunit(bp->b_dev);
+       struct disklabel *lp = &dklabel[unit];
+       int status = dcb->operrsta;
+       int blkdone;
+
+       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 (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)
@@ -774,9 +955,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) {
 
@@ -794,49 +976,85 @@ 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;
+
+       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;
+
+                       if (error == 0 && dk->dk_state == OPENRAW &&
+                           vdreset_drive(vddinfo[unit]))
+                               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;
 
                break;
 
-       case DIOCWDINFO: {
-               struct buf *bp;
-               struct disklabel *dlp;
+       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 = dev;
-               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);
 }
 
 /*
 }
 
 /*
@@ -846,7 +1064,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++) {
@@ -854,21 +1073,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) {
-                       for (unit = 0; unit < NDK; unit++)
-                               if (dkutab[unit].b_active &&
-                                   vddinfo[unit]->ui_mi == vm)
-                                       goto active;
-                       vd->vd_wticks = 0;
-                       continue;
-               }
-active:
-               vd->vd_wticks++;
-               if (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);
        }
 }
 
        }
 }
 
@@ -885,40 +1098,41 @@ vddump(dev)
        register struct vdsoftc *vd;
        struct dksoftc *dk;
        int part, unit, num;
        register struct vdsoftc *vd;
        struct dksoftc *dk;
        int part, unit, num;
-       caddr_t start;
+       u_long start;
 
        start = 0;
        unit = vdunit(dev);
        if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
                return (ENXIO);
        dk = &dksoftc[unit];
 
        start = 0;
        unit = vdunit(dev);
        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);
        /*
-        * Dumplo and maxfree are in pages.
+        * Maxfree is in pages, dumplo is in DEV_BSIZE units.
         */
        num = maxfree * (NBPG / lp->d_secsize);
         */
        num = maxfree * (NBPG / lp->d_secsize);
-       dumplo *= NBPG / lp->d_secsize;
+       dumplo *= DEV_BSIZE / lp->d_secsize;
        if (dumplo + num >= lp->d_partitions[vdpart(dev)].p_size)
                num = lp->d_partitions[vdpart(dev)].p_size - dumplo;
        vd = &vdsoftc[vm->um_ctlr];
        vd->vd_dcb.intflg = DCBINT_NONE;
        vd->vd_dcb.opcode = VDOP_WD;
        if (dumplo + num >= lp->d_partitions[vdpart(dev)].p_size)
                num = lp->d_partitions[vdpart(dev)].p_size - dumplo;
        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.trailcnt = sizeof (trrw) / sizeof (long);
+       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;
 
                nsec = MIN(num, DBSIZE);
        while (num > 0) {
                int nsec, cn, sn, tn;
 
                nsec = MIN(num, DBSIZE);
-               sn = dumplo + (unsigned)start / lp->d_secsize;
+               sn = dumplo + start / lp->d_secsize;
                cn = (sn + lp->d_partitions[vdpart(dev)].p_offset) /
                    lp->d_secpercyl;
                sn %= lp->d_secpercyl;
                cn = (sn + lp->d_partitions[vdpart(dev)].p_offset) /
                    lp->d_secpercyl;
                sn %= lp->d_secpercyl;
@@ -959,7 +1173,11 @@ vdsize(dev)
            (dk = &dksoftc[unit])->dk_state != OPEN)
                return (-1);
        lp = &dklabel[unit];
            (dk = &dksoftc[unit])->dk_state != OPEN)
                return (-1);
        lp = &dklabel[unit];
+#ifdef SECSIZE
        return ((int)lp->d_partitions[vdpart(dev)].p_size);
        return ((int)lp->d_partitions[vdpart(dev)].p_size);
+#else SECSIZE
+       return ((int)lp->d_partitions[vdpart(dev)].p_size >> dk->dk_bshift);
+#endif SECSIZE
 }
 
 /*
 }
 
 /*
@@ -983,7 +1201,7 @@ vdreset_ctlr(vm)
                vdaddr->vdccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
                    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
        }
                vdaddr->vdccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
                    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
        }
-       if (!vdcmd(vm, VDOP_INIT, 10) || !vdcmd(vm, VDOP_DIAG, 10)) {
+       if (!vdcmd(vm, VDOP_INIT, 10, 0) || !vdcmd(vm, VDOP_DIAG, 10, 0)) {
                printf("%s cmd failed\n",
                    vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
                return;
                printf("%s cmd failed\n",
                    vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
                return;
@@ -999,21 +1217,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.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 (treset) / sizeof (long);
+               vd->vd_dcb.trailcnt = sizeof (struct treset) / sizeof (long);
                vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
                vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
-               vd->vd_dcb.trail.rstrail.slip_sec = lp->d_trackskew;
-               vd->vd_dcb.trail.rstrail.recovery = 0x18f;
+               vd->vd_dcb.trail.rstrail.slip_sec = lp->d_sparespertrack;
+               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;
@@ -1023,32 +1242,58 @@ top:
                printf(" during config\n");
                return (0);
        }
                printf(" during config\n");
                return (0);
        }
+/*
+uncache(&vd->vd_dcb.err_code);
+printf("vdreset_drive %d, error %b, ecode %x, status %x => ",
+   vi->ui_unit, vd->vd_dcb.operrsta, VDERRBITS, vd->vd_dcb.err_code,
+   vdaddr->vdstatus[vi->ui_slave]);
+uncache(&vdaddr->vdstatus[vi->ui_slave]);
+printf("%x =>", vdaddr->vdstatus[vi->ui_slave]);
+{ int status = vd->vd_dcb.operrsta;
+vdcmd(vm, VDOP_STATUS, 5, vi->ui_slave);
+vd->vd_dcb.operrsta = status;
+}
+uncache(&vdaddr->vdstatus[vi->ui_slave]);
+printf("%x\n", vdaddr->vdstatus[vi->ui_slave]);
+*/
        if (vd->vd_dcb.operrsta & VDERR_HARD) {
        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\n");
+                       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);
 }
 
 /*
  * Perform a command w/o trailer.
  */
        return (1);
 }
 
 /*
  * Perform a command w/o trailer.
  */
-vdcmd(vm, cmd, t)
+vdcmd(vm, cmd, t, slave)
        register struct vba_ctlr *vm;
 {
        register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
        register struct vba_ctlr *vm;
 {
        register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
@@ -1057,7 +1302,7 @@ vdcmd(vm, cmd, t)
        vd->vd_dcb.intflg = DCBINT_NONE;
        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        vd->vd_dcb.operrsta = 0;
        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 = 0;
+       vd->vd_dcb.devselect = slave;
        vd->vd_dcb.trailcnt = 0;
        vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        vd->vd_mdcb.mdcb_status = 0;
        vd->vd_dcb.trailcnt = 0;
        vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        vd->vd_mdcb.mdcb_status = 0;
@@ -1088,7 +1333,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);
@@ -1098,7 +1342,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);
@@ -1110,71 +1355,92 @@ 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 */
        },
        },
-       { 44, 20, 842, "egl",
-               {0,      26400},        /* egl0a cyl   0 - 59 */
-               {26400,  33000},        /* egl0b cyl  60 - 134 */
-               {59400,  308880},       /* egl0c cyl 135 - 836 */
-               {368280, 2640},         /* egl0d cyl 837 - 842 */
-               {0, 368280},            /* egl0e cyl 0 - 836 */
-               {0, 370920},            /* egl0f cyl 0 - 842 */
-               {59400, 155320},        /* egl0g cyl 135 - 487 */
-               {214720, 153560}        /* egl0h cyl 488 - 836 */
+       { 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 */
        },
        },
-       { 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 */
+       { 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 */
        },
        },
-       { 32, 24, 711, "xfd",
-               { 0,     20352 },       /* a cyl   0 - 52 */
-               { 20352, 20352 },       /* b cyl  53 - 105 */
-               { 40704, 230400 },      /* c cyl 106 - 705 */
-               { 0,     40704 },       /* d cyl 709 - 710 (a & b) */
-               { 0,     271104 },      /* e cyl   0 - 705 */
-               { 20352, 250752 },      /* f cyl  53 - 705 (b & c) */
-               { 40704, 115200 },      /* g cyl 106 - 405 (1/2 of c) */
-               { 155904,115200 }       /* h cyl 406 - 705 (1/2 of c) */
+       { 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,      736560},       /* egl0e cyl   0 - 836 */
+               {0,      740960},       /* egl0f cyl   0 - 841 */
+               {118800, 310640},       /* egl0g cyl 135 - 487 */
+               {429440, 307120}        /* egl0h cyl 488 - 836 */
        },
        },
-       { 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 */
+       { 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, 10, 823, "fsd",
-               {0,      9600},         /* a cyl   0 -  59 */
-               {9600,   12000},        /* b cyl  60 - 134 */
-               {21600,  109280},       /* c cyl 135 - 817 */
-               {39840,  91040},        /* d cyl 249 - 817 */
-               {58080,  72800},        /* e cyl 363 - 817 */
-               {76320,  54560},        /* f cyl 477 - 817 */
-               {94560,  36320},        /* g cyl 591 - 817 */
-               {112800, 18080}         /* h cyl 705 - 817 */
+       { 32, 24, 711, 512, "xfd",
+               { 0,     40704 },       /* a cyl   0 - 52 */
+               { 40704, 40704 },       /* b cyl  53 - 105 */
+               { 81408, 460800 },      /* c cyl 106 - 705 */
+               { 0,     81408 },       /* d cyl 709 - 710 (a & b) */
+               { 0,     542208 },      /* e cyl   0 - 705 */
+               { 40704, 501504 },      /* f cyl  53 - 705 (b & c) */
+               { 81408, 230400 },      /* g cyl 106 - 405 (1/2 of c) */
+               { 311808,230400 }       /* h cyl 406 - 705 (1/2 of c) */
+       },
+       { 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 */
+       },
+       { 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 */
        }
 };
 #define        NVDST   (sizeof (vdst) / sizeof (vdst[0]))
        }
 };
 #define        NVDST   (sizeof (vdst) / sizeof (vdst[0]))
@@ -1191,7 +1457,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];
@@ -1201,16 +1467,19 @@ 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;
+               DELAY(100000);
                if (!vdreset_drive(vi))
                        return (0);
                if (!vdreset_drive(vi))
                        return (0);
+               DELAY(100000);
                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.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.trailcnt = sizeof (trrw) / sizeof (long);
-               vd->vd_dcb.trail.rwtrail.memadr = (char *)
-                   vtoph((struct proc *)0, (unsigned)vd->vd_rawbuf);
-               vd->vd_dcb.trail.rwtrail.wcount = 512 / sizeof(short);
+               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.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;
@@ -1223,18 +1492,15 @@ 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;
        }
        lp->d_npartitions = 8;
        lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        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;
        }
        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);
 }