new diskerr routine
[unix-history] / usr / src / sys / vax / mba / hp.c
index f3bb811..f461115 100644 (file)
@@ -3,7 +3,7 @@
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)hp.c        7.6 (Berkeley) %G%
+ *     @(#)hp.c        7.11 (Berkeley) %G%
  */
 
 #ifdef HPDEBUG
  */
 
 #ifdef HPDEBUG
@@ -105,20 +105,27 @@ u_char    hp_offset[16] = {
     0, 0, 0, 0,
 };
 
     0, 0, 0, 0,
 };
 
-struct buf     rhpbuf[NHP];
 struct disklabel hplabel[NHP];
 struct dkbad   hpbad[NHP];
 
 struct hpsoftc {
        u_char  sc_recal;       /* recalibrate state */
        u_char  sc_doseeks;     /* perform explicit seeks */
 struct disklabel hplabel[NHP];
 struct dkbad   hpbad[NHP];
 
 struct hpsoftc {
        u_char  sc_recal;       /* recalibrate state */
        u_char  sc_doseeks;     /* perform explicit seeks */
+#ifdef COMPAT_42
+       u_char  sc_hdr;         /* next i/o includes header */
+#endif
        int     sc_state;       /* open fsm */
        int     sc_state;       /* open fsm */
-       long    sc_openpart;    /* bit mask of open subunits */
-       long    sc_copenpart;   /* bit mask of open character subunits */
-       long    sc_bopenpart;   /* bit mask of open block subunits */
+       int     sc_wlabel;      /* label sector is currently writable */
+       u_long  sc_openpart;    /* bit mask of open subunits */
+       u_long  sc_copenpart;   /* bit mask of open character subunits */
+       u_long  sc_bopenpart;   /* bit mask of open block subunits */
        daddr_t sc_mlsize;      /* ML11 size */
        int     sc_blkdone;     /* amount sucessfully transfered */
        daddr_t sc_badbn;       /* replacement block number */
        daddr_t sc_mlsize;      /* ML11 size */
        int     sc_blkdone;     /* amount sucessfully transfered */
        daddr_t sc_badbn;       /* replacement block number */
+       int     sc_status;      /* copy of drive status reg. after format */
+       int     sc_hpds;        /* copy of hpds reg. after format */
+       int     sc_er1;         /* copy of error reg. 1 after format */
+       int     sc_er2;         /* copy of error reg. 2 after format */
 } hpsoftc[NHP];
 
 /*
 } hpsoftc[NHP];
 
 /*
@@ -158,17 +165,21 @@ hpattach(mi, slave)
        struct mba_device *mi;
 {
        register int unit = mi->mi_unit;
        struct mba_device *mi;
 {
        register int unit = mi->mi_unit;
+       extern int cold;
 
 
-       /*
-        * Try to initialize device and read pack label.
-        */
-       if (hpinit(hpminor(unit, 0), 0) == 0) {
-               printf(": %s", hplabel[unit].d_typename);
+       if (cold) {
+               /*
+                * Try to initialize device and read pack label.
+                */
+               if (hpinit(hpminor(unit, 0), 0) == 0) {
+                       printf(": %s", hplabel[unit].d_typename);
 #ifdef notyet
 #ifdef notyet
-               addswap(makedev(HPMAJOR, hpminor(unit, 0)), &hplabel[unit]);
+                       addswap(makedev(HPMAJOR, hpminor(unit, 0)),
+                           &hplabel[unit]);
 #endif
 #endif
-       } else
-               printf(": offline");
+               } else
+                       printf(": offline");
+       }
 }
 
 hpopen(dev, flags, fmt)
 }
 
 hpopen(dev, flags, fmt)
@@ -204,8 +215,7 @@ hpopen(dev, flags, fmt)
         * unless one is the "raw" partition (whole disk).
         */
 #define        RAWPART         2               /* 'c' partition */     /* XXX */
         * unless one is the "raw" partition (whole disk).
         */
 #define        RAWPART         2               /* 'c' partition */     /* XXX */
-       if ((sc->sc_openpart & (1 << part)) == 0 &&
-           part != RAWPART) {
+       if ((sc->sc_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;
@@ -235,6 +245,7 @@ hpopen(dev, flags, fmt)
        return (0);
 }
 
        return (0);
 }
 
+/* ARGSUSED */
 hpclose(dev, flags, fmt)
        dev_t dev;
        int flags, fmt;
 hpclose(dev, flags, fmt)
        dev_t dev;
        int flags, fmt;
@@ -254,8 +265,8 @@ hpclose(dev, flags, fmt)
                sc->sc_bopenpart &= ~mask;
                break;
        }
                sc->sc_bopenpart &= ~mask;
                break;
        }
-       if (((sc->sc_copenpart | sc->sc_bopenpart) & mask) == 0)
-               sc->sc_openpart &= ~mask;
+       sc->sc_openpart = sc->sc_copenpart | sc->sc_bopenpart;
+
        /*
         * 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().
@@ -266,6 +277,7 @@ hpclose(dev, flags, fmt)
                        sleep((caddr_t)sc, PZERO - 1);
                splx(s);
                sc->sc_state = CLOSED;
                        sleep((caddr_t)sc, PZERO - 1);
                splx(s);
                sc->sc_state = CLOSED;
+               sc->sc_wlabel = 0;
        }
        return (0);
 }
        }
        return (0);
 }
@@ -282,7 +294,6 @@ hpinit(dev, flags)
        struct dkbad *db;
        char *msg, *readdisklabel();
        int unit, i, error = 0;
        struct dkbad *db;
        char *msg, *readdisklabel();
        int unit, i, error = 0;
-       extern int cold;
 
        unit = hpunit(dev);
        sc = &hpsoftc[unit];
 
        unit = hpunit(dev);
        sc = &hpsoftc[unit];
@@ -295,10 +306,12 @@ hpinit(dev, flags)
         * Use the default sizes until we've read the label,
         * or longer if there isn't one there.
         */
         * Use the default sizes until we've read the label,
         * or longer if there isn't one there.
         */
-       lp->d_secsize = DEV_BSIZE;
-       lp->d_nsectors = 32;
-       lp->d_ntracks = 20;
-       lp->d_secpercyl = 32*20;
+       if (lp->d_secpercyl == 0) {
+               lp->d_secsize = DEV_BSIZE;
+               lp->d_nsectors = 32;
+               lp->d_ntracks = 20;
+               lp->d_secpercyl = 32*20;
+       }
 
        if (flags & O_NDELAY)
                goto raw;
 
        if (flags & O_NDELAY)
                goto raw;
@@ -309,7 +322,6 @@ hpinit(dev, flags)
         * Set up dummy label with all that's needed.
         */
        if (mi->mi_type == MBDT_ML11A || mi->mi_type == MBDT_ML11B) {
         * Set up dummy label with all that's needed.
         */
        if (mi->mi_type == MBDT_ML11A || mi->mi_type == MBDT_ML11B) {
-               register struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
                register int trt;
 
                sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
                register int trt;
 
                sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
@@ -335,10 +347,9 @@ hpinit(dev, flags)
                else
                        log(LOG_ERR, "hp%d: %s\n", unit, msg);
 #ifdef COMPAT_42
                else
                        log(LOG_ERR, "hp%d: %s\n", unit, msg);
 #ifdef COMPAT_42
-               mi->mi_type = hpmaptype(mi, lp);
-#else
-               goto raw;
+               if ((mi->mi_type = hpmaptype(mi, lp)) == 0)
 #endif
 #endif
+               goto raw;
        }
 
        /*
        }
 
        /*
@@ -368,22 +379,24 @@ hpinit(dev, flags)
        if ((bp->b_flags & B_ERROR) == 0 && db->bt_mbz == 0 &&
            db->bt_flag == 0) {
                hpbad[unit] = *db;
        if ((bp->b_flags & B_ERROR) == 0 && db->bt_mbz == 0 &&
            db->bt_flag == 0) {
                hpbad[unit] = *db;
-               sc->sc_state = OPEN;
        } else {
                log(LOG_ERR, "hp%d: %s bad-sector file\n", unit,
                    (bp->b_flags & B_ERROR) ? "can't read" : "format error in");
                u.u_error = 0;                          /* XXX */
        } else {
                log(LOG_ERR, "hp%d: %s bad-sector file\n", unit,
                    (bp->b_flags & B_ERROR) ? "can't read" : "format error in");
                u.u_error = 0;                          /* XXX */
-               sc->sc_state = OPENRAW;
        }
        }
+       sc->sc_state = OPEN;
        bp->b_flags = B_INVAL | B_AGE;
        brelse(bp);
        bp->b_flags = B_INVAL | B_AGE;
        brelse(bp);
-done:
        wakeup((caddr_t)sc);
        return (error);
 
 raw:
        wakeup((caddr_t)sc);
        return (error);
 
 raw:
-       sc->sc_state = OPENRAW;
-       wakeup((caddr_t)sc);
+       if (cold)
+               sc->sc_state = CLOSED;
+       else {
+               sc->sc_state = OPENRAW;
+               wakeup((caddr_t)sc);
+       }
        return (error);
 }
 
        return (error);
 }
 
@@ -411,13 +424,32 @@ hpstrategy(bp)
                bp->b_error = ENXIO;
                goto bad;
        }
                bp->b_error = ENXIO;
                goto bad;
        }
+#ifdef COMPAT_42
+       if (sc->sc_hdr) {                               /* XXX */
+               if (bp->b_bcount == 516)
+                       bp->b_flags |= B_FORMAT;
+               sc->sc_hdr = 0;
+       }
+#endif
        if (sc->sc_state < OPEN)
                goto q;
        if (sc->sc_state < OPEN)
                goto q;
+       if (sc->sc_state != OPEN && (bp->b_flags & B_READ) == 0) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
        if ((sc->sc_openpart & (1 << xunit)) == 0) {
                bp->b_error = ENODEV;
                goto bad;
        }
        maxsz = lp->d_partitions[xunit].p_size;
        if ((sc->sc_openpart & (1 << xunit)) == 0) {
                bp->b_error = ENODEV;
                goto bad;
        }
        maxsz = lp->d_partitions[xunit].p_size;
+       if (bp->b_blkno + lp->d_partitions[xunit].p_offset <= LABELSECTOR &&
+#if LABELSECTOR != 0
+           bp->b_blkno + lp->d_partitions[xunit].p_offset + sz > LABELSECTOR &&
+#endif
+           (bp->b_flags & B_READ) == 0 && sc->sc_wlabel == 0) {
+               bp->b_error = EROFS;
+               goto bad;
+       }
        if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
                if (bp->b_blkno == maxsz) {
                        bp->b_resid = bp->b_bcount;
        if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
                if (bp->b_blkno == maxsz) {
                        bp->b_resid = bp->b_bcount;
@@ -584,29 +616,36 @@ hpdtint(mi, mbsr)
        register int er1, er2;
        struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
        int retry = 0;
        register int er1, er2;
        struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
        int retry = 0;
-       int npf;
-       daddr_t bn;
-       int bcr;
+       int npf, bcr;
 
        bcr = MASKREG(-mi->mi_mba->mba_bcr);
 
        bcr = MASKREG(-mi->mi_mba->mba_bcr);
+       if (bp->b_flags & B_FORMAT) {
+               sc->sc_status = mbsr;
+               sc->sc_hpds = hpaddr->hpds;
+               sc->sc_er1 = hpaddr->hper1;
+               sc->sc_er2 = hpaddr->hper2;
+       }
        if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
                er1 = hpaddr->hper1;
                er2 = hpaddr->hper2;
        if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
                er1 = hpaddr->hper1;
                er2 = hpaddr->hper2;
-               if (bp->b_flags & B_BAD) {
+               if (bp->b_flags & B_BAD)
                        npf = bp->b_error;
                        npf = bp->b_error;
-                       bn = sc->sc_badbn;
-               } else {
-                       npf = btop(bp->b_bcount - bcr);
+               else {
+                       npf = btodb(bp->b_bcount + (DEV_BSIZE - 1) - bcr);
                        if (er1 & (HPER1_DCK | HPER1_ECH))
                                npf--;
                        if (er1 & (HPER1_DCK | HPER1_ECH))
                                npf--;
-                       bn = bp->b_blkno + npf;
                }
                if (HPWAIT(mi, hpaddr) == 0)
                        goto hard;
 #ifdef HPDEBUG
                if (hpdebug) {
                        int dc = hpaddr->hpdc, da = hpaddr->hpda;
                }
                if (HPWAIT(mi, hpaddr) == 0)
                        goto hard;
 #ifdef HPDEBUG
                if (hpdebug) {
                        int dc = hpaddr->hpdc, da = hpaddr->hpda;
+                       daddr_t bn;
 
 
+                       if (bp->b_flags & B_BAD)
+                               bn = sc->sc_badbn;
+                       else
+                               bn = bp->b_blkno + npf;
                        log(LOG_DEBUG,
                    "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n",
                                bp, bp->b_cylin, bn, sc->sc_blkdone,
                        log(LOG_DEBUG,
                    "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n",
                                bp, bp->b_cylin, bn, sc->sc_blkdone,
@@ -627,7 +666,7 @@ hpdtint(mi, mbsr)
                            hpunit(bp->b_dev));
                        bp->b_flags |= B_ERROR;
                } else if (bp->b_flags & B_FORMAT) {
                            hpunit(bp->b_dev));
                        bp->b_flags |= B_ERROR;
                } else if (bp->b_flags & B_FORMAT) {
-                       goto hard;
+                       bp->b_flags |= B_ERROR;
                } else if (RM80(mi->mi_type) && er2&HPER2_SSE) {
                        (void) hpecc(mi, SSE);
                        return (MBD_RESTARTED);
                } else if (RM80(mi->mi_type) && er2&HPER2_SSE) {
                        (void) hpecc(mi, SSE);
                        return (MBD_RESTARTED);
@@ -664,16 +703,16 @@ hpdtint(mi, mbsr)
                    er1 & HPER1_HARD ||
                    (!ML11(mi->mi_type) && (er2 & HPER2_HARD))) {
 hard:
                    er1 & HPER1_HARD ||
                    (!ML11(mi->mi_type) && (er2 & HPER2_HARD))) {
 hard:
-                       bp->b_blkno = bn;               /* XXX */
-                       harderr(bp, "hp");
+                       diskerr(bp, "hp", "hard error", LOG_PRINTF, npf,
+                           &hplabel[mi->mi_unit]);
+                       if (bp->b_flags & B_BAD)
+                               printf(" (on replacement sector %d)",
+                                   sc->sc_badbn);
                        if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
                        if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
-                               printf("mbsr=%b ", mbsr, mbsr_bits);
-                       printf("er1=%b er2=%b",
+                               printf(" mbsr=%b", mbsr, mbsr_bits);
+                       printf(" er1=%b er2=%b\n",
                            MASKREG(hpaddr->hper1), HPER1_BITS,
                            MASKREG(hpaddr->hper2), HPER2_BITS);
                            MASKREG(hpaddr->hper1), HPER1_BITS,
                            MASKREG(hpaddr->hper2), HPER2_BITS);
-                       if (bp->b_flags & B_FORMAT)
-                               printf(" (hdr i/o)");
-                       printf("\n");
                        bp->b_flags |= B_ERROR;
                        bp->b_flags &= ~B_BAD;
                } else
                        bp->b_flags |= B_ERROR;
                        bp->b_flags &= ~B_BAD;
                } else
@@ -707,13 +746,11 @@ hard:
                (void)HPWAIT(mi, hpaddr);
                mbclrattn(mi);
        }
                (void)HPWAIT(mi, hpaddr);
                mbclrattn(mi);
        }
-       if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0)
-               log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n",
-                   hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07),
-                   mi->mi_tab.b_errcnt,
-                   (bp->b_flags & B_READ) ? "read" : "writ",
-                   (bp->b_flags & B_BAD) ?
-                   sc->sc_badbn : bp->b_blkno + sc->sc_blkdone);
+       if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0) {
+               diskerr(bp, "hp", "retries", LOG_INFO, sc->sc_blkdone,
+                   &hplabel[mi->mi_unit]);
+               addlog(": %d retries\n", mi->mi_tab.b_errcnt);
+       }
        if ((bp->b_flags & B_BAD) && hpecc(mi, CONT))
                return (MBD_RESTARTED);
        sc->sc_blkdone = 0;
        if ((bp->b_flags & B_BAD) && hpecc(mi, CONT))
                return (MBD_RESTARTED);
        sc->sc_blkdone = 0;
@@ -744,28 +781,6 @@ hpwait(mi)
        return (i);
 }
 
        return (i);
 }
 
-hpread(dev, uio)
-       dev_t dev;
-       struct uio *uio;
-{
-       register int unit = hpunit(dev);
-
-       if (unit >= NHP)
-               return (ENXIO);
-       return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
-}
-
-hpwrite(dev, uio)
-       dev_t dev;
-       struct uio *uio;
-{
-       register int unit = hpunit(dev);
-
-       if (unit >= NHP)
-               return (ENXIO);
-       return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
-}
-
 hpioctl(dev, cmd, data, flag)
        dev_t dev;
        int cmd;
 hpioctl(dev, cmd, data, flag)
        dev_t dev;
        int cmd;
@@ -774,8 +789,8 @@ hpioctl(dev, cmd, data, flag)
 {
        int unit = hpunit(dev);
        register struct disklabel *lp;
 {
        int unit = hpunit(dev);
        register struct disklabel *lp;
-       register struct format_op *fop;
-       int error = 0;
+       register struct hpsoftc *sc = &hpsoftc[unit];
+       int error = 0, wlab;
        int hpformat();
 
        lp = &hplabel[unit];
        int hpformat();
 
        lp = &hplabel[unit];
@@ -796,69 +811,85 @@ hpioctl(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,
+                           (sc->sc_state == OPENRAW) ? 0 : sc->sc_openpart);
+               if (error == 0)
+                       sc->sc_state = OPEN;
+               break;
+
+       case DIOCWLABEL:
+               if ((flag & FWRITE) == 0)
+                       error = EBADF;
+               else
+                       sc->sc_wlabel = *(int *)data;
                break;
 
        case DIOCWDINFO:
                break;
 
        case DIOCWDINFO:
-               if ((flag & FWRITE) == 0) {
+               /* simulate opening partition 0 so write succeeds */
+               sc->sc_openpart |= (1 << 0);            /* XXX */
+               wlab = sc->sc_wlabel;
+               sc->sc_wlabel = 1;
+               if ((flag & FWRITE) == 0)
                        error = EBADF;
                        error = EBADF;
-                       break;
-               }
-               {
-               struct buf *bp;
-               struct disklabel *dlp;
-
-               *lp = *(struct disklabel *)data;
-               bp = geteblk(lp->d_secsize);
-               bp->b_dev = makedev(major(dev), hpminor(hpunit(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);
-               hpstrategy(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;
-               hpstrategy(bp);
-               biowait(bp);
-               if (bp->b_flags & B_ERROR) {
-                       error = u.u_error;              /* XXX */
-                       u.u_error = 0;
-               }
-bad:
-               brelse(bp);
+               else if ((error = setdisklabel(lp, (struct disklabel *)data,
+                   (sc->sc_state == OPENRAW) ? 0 : sc->sc_openpart)) == 0) {
+                       sc->sc_state = OPEN;
+                       error = writedisklabel(dev, hpstrategy, lp);
                }
                }
+               sc->sc_openpart = sc->sc_copenpart | sc->sc_bopenpart;
+               sc->sc_wlabel = wlab;
                break;
 
                break;
 
-#ifdef notyet
-       case DIOCWFORMAT:
-               if ((flag & FWRITE) == 0) {
+       case DIOCSBAD:
+           {
+               struct dkbad *db = (struct dkbad *)data;
+
+               if ((flag & FWRITE) == 0)
                        error = EBADF;
                        error = EBADF;
-                       break;
-               }
-               {
+               else if (db->bt_mbz != 0 || db->bt_flag != 0)
+                       error = EINVAL;
+               else
+                       hpbad[unit] = *db;
+               break;
+           }
+
+       case DIOCRFORMAT:
+       case DIOCWFORMAT:
+           {
+               register struct format_op *fop;
                struct uio auio;
                struct iovec aiov;
 
                struct uio auio;
                struct iovec aiov;
 
+               if (cmd == DIOCWFORMAT && (flag & FWRITE) == 0) {
+                       error = EBADF;
+                       break;
+               }
                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;
                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 = 0;
+               auio.uio_segflg = UIO_USERSPACE;
                auio.uio_offset = fop->df_startblk * lp->d_secsize;
                auio.uio_offset = fop->df_startblk * lp->d_secsize;
-               error = physio(hpformat, &rhpbuf[unit], dev, B_WRITE,
-                       minphys, &auio);
+               /*
+                * 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(hpformat, (struct buf *)NULL, dev,
+                   (cmd == DIOCWFORMAT ? B_WRITE : B_READ), minphys, &auio);
                fop->df_count -= auio.uio_resid;
                fop->df_reg[0] = sc->sc_status;
                fop->df_count -= auio.uio_resid;
                fop->df_reg[0] = sc->sc_status;
-               fop->df_reg[1] = sc->sc_error;
-               }
+               fop->df_reg[1] = sc->sc_hpds;
+               fop->df_reg[2] = sc->sc_er1;
+               fop->df_reg[3] = sc->sc_er2;
+               break;
+           }
+
+#ifdef COMPAT_42
+       case DKIOCHDR:  /* do header read/write */      /* XXX */
+               sc->sc_hdr = 1;
                break;
 #endif
 
                break;
 #endif
 
@@ -872,9 +903,8 @@ bad:
 hpformat(bp)
        struct buf *bp;
 {
 hpformat(bp)
        struct buf *bp;
 {
-
        bp->b_flags |= B_FORMAT;
        bp->b_flags |= B_FORMAT;
-       return (hpstrategy(bp));
+       hpstrategy(bp);
 }
 
 hpecc(mi, flag)
 }
 
 hpecc(mi, flag)
@@ -920,11 +950,10 @@ hpecc(mi, flag)
                int bit, byte, mask;
 
                npf--;          /* because block in error is previous block */
                int bit, byte, mask;
 
                npf--;          /* because block in error is previous block */
-               bn--;
+               diskerr(bp, "hp", "soft ecc", LOG_WARNING, npf, lp);
                if (bp->b_flags & B_BAD)
                if (bp->b_flags & B_BAD)
-                       bn = sc->sc_badbn;
-               log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev),
-                   'a'+(minor(bp->b_dev)&07), bn);
+                       addlog(" (on replacement sector %d)", sc->sc_badbn);
+               addlog("\n");
                mask = MASKREG(rp->hpec2);
                i = MASKREG(rp->hpec1) - 1;             /* -1 makes 0 origin */
                bit = i&07;
                mask = MASKREG(rp->hpec2);
                i = MASKREG(rp->hpec1) - 1;             /* -1 makes 0 origin */
                bit = i&07;
@@ -1051,7 +1080,7 @@ hpdump(dev)
                daddr_t bn;
 
                blk = num > DBSIZE ? DBSIZE : num;
                daddr_t bn;
 
                blk = num > DBSIZE ? DBSIZE : num;
-               bn = dumplo + btop(start);
+               bn = dumplo + btodb(start);
                cn = (bn + lp->d_partitions[hppart(dev)].p_offset) /
                    lp->d_secpercyl;
                sn = bn % lp->d_secpercyl;
                cn = (bn + lp->d_partitions[hppart(dev)].p_offset) /
                    lp->d_secpercyl;
                sn = bn % lp->d_secpercyl;
@@ -1324,20 +1353,27 @@ hpmaptype(mi, lp)
                            hpst[type].ncyl == ncyl)
                                break;
 
                            hpst[type].ncyl == ncyl)
                                break;
 
+               hpaddr->hpcs1 = HP_DCLR|HP_GO;
+               mbclrattn(mi);          /* conservative */
                if (hptypes[type] == 0) {
        printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n",
                                mi->mi_unit, nsectors, ntracks, ncyl);
                if (hptypes[type] == 0) {
        printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n",
                                mi->mi_unit, nsectors, ntracks, ncyl);
-                       type = HPDT_RM02;
+                       lp->d_nsectors = nsectors;
+                       lp->d_ntracks = ntracks;
+                       lp->d_ncylinders = ncyl;
+                       lp->d_secpercyl = nsectors*ntracks;
+                       lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
+                       lp->d_npartitions = 1;
+                       lp->d_partitions[0].p_offset = 0;
+                       lp->d_partitions[0].p_size = lp->d_secperunit;
+                       return (0);
                }
                }
-               hpaddr->hpcs1 = HP_DCLR|HP_GO;
-               mbclrattn(mi);          /* conservative */
        }
 
        /*
         * set up minimal disk label.
         */
        st = &hpst[type];
        }
 
        /*
         * set up minimal disk label.
         */
        st = &hpst[type];
-       lp->d_secsize = 512;
        lp->d_nsectors = st->nsect;
        lp->d_ntracks = st->ntrak;
        lp->d_secpercyl = st->nspc;
        lp->d_nsectors = st->nsect;
        lp->d_ntracks = st->ntrak;
        lp->d_secpercyl = st->nspc;