merge latest Utah hp300 code including 68040 support
[unix-history] / usr / src / sys / hp300 / dev / rd.c
index e7101e1..57a8d17 100644 (file)
@@ -9,9 +9,9 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- * from: Utah $Hdr: rd.c 1.30 89/09/17$
+ * from: Utah $Hdr: rd.c 1.38 90/10/12$
  *
  *
- *     @(#)rd.c        7.1 (Berkeley) %G%
+ *     @(#)rd.c        7.14 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
 #include "rd.h"
 #if NRD > 0
 
 #include "rd.h"
 #if NRD > 0
 
-#include "param.h"
-#include "systm.h"
-#include "errno.h"
-#include "dkstat.h"
-#include "disklabel.h"
-#include "buf.h"
-#include "uio.h"
+#include "sys/param.h"
+#include "sys/systm.h"
+#include "sys/errno.h"
+#include "sys/dkstat.h"
+#include "sys/disklabel.h"
+#include "sys/buf.h"
+#include "sys/uio.h"
 
 
-#include "device.h"
+#include "hp/dev/device.h"
 #include "rdreg.h"
 
 #include "rdreg.h"
 
+#include "vm/vm_param.h"
+#include "vm/lock.h"
+#include "vm/vm_prot.h"
+#include "vm/pmap.h"
+
 int    rdinit(), rdstart(), rdgo(), rdintr();
 struct driver rddriver = {
        rdinit, "rd", rdstart, rdgo, rdintr,
 int    rdinit(), rdstart(), rdgo(), rdintr();
 struct driver rddriver = {
        rdinit, "rd", rdstart, rdgo, rdintr,
@@ -38,19 +43,20 @@ struct      driver rddriver = {
 
 struct rd_softc {
        struct  hp_device *sc_hd;
 
 struct rd_softc {
        struct  hp_device *sc_hd;
+       int     sc_flags;
+       short   sc_type;
+       short   sc_punit;
+       char    *sc_addr;
+       int     sc_resid;
+       u_int   sc_wpms;
+       struct  rdinfo *sc_info;
+       struct  devqueue sc_dq;
        struct  rd_iocmd sc_ioc;
        struct  rd_rscmd sc_rsc;
        struct  rd_stat sc_stat;
        struct  rd_ssmcmd sc_ssmc;
        struct  rd_srcmd sc_src;
        struct  rd_clearcmd sc_clear;
        struct  rd_iocmd sc_ioc;
        struct  rd_rscmd sc_rsc;
        struct  rd_stat sc_stat;
        struct  rd_ssmcmd sc_ssmc;
        struct  rd_srcmd sc_src;
        struct  rd_clearcmd sc_clear;
-       int     sc_resid;
-       char    *sc_addr;
-       struct  rdinfo *sc_info;
-       int     sc_flags;
-       short   sc_type;
-       short   sc_punit;
-       struct  devqueue sc_dq;
 } rd_softc[NRD];
 
 /* sc_flags values */
 } rd_softc[NRD];
 
 /* sc_flags values */
@@ -277,6 +283,25 @@ struct size rd7945A_sizes[8] = {
        RDSZ(207900),   1022,           /* F=cyl 1022 thru 1571 */
        RDSZ(528444),   174,            /* G=cyl 174 thru 1571 */
        RDSZ(511812),   218,            /* H=cyl 218 thru 1571 */
        RDSZ(207900),   1022,           /* F=cyl 1022 thru 1571 */
        RDSZ(528444),   174,            /* G=cyl 174 thru 1571 */
        RDSZ(511812),   218,            /* H=cyl 218 thru 1571 */
+}, rd2200A_sizes[8] = {
+       RDSZ(16272),    1,              /* A=cyl 1 thru 36 */
+       RDSZ(49720),    37,             /* B=cyl 37 thru 146 */
+       RDSZ(654948),   0,              /* C=cyl 0 thru 1448 */
+       RDSZ(65992),    37,             /* D=cyl 37 thru 182 */
+       RDSZ(304648),   183,            /* E=cyl 183 thru 856 */
+       RDSZ(267584),   857,            /* F=cyl 857 thru 1448 */
+       RDSZ(588504),   147,            /* G=cyl 147 thru 1448 */
+       RDSZ(572232),   183,            /* H=cyl 183 thru 1448 */
+}, rd2203A_sizes[8] = {
+       /* modelled after the 7937; i.e. bogus */
+       RDSZ(16272),    1,              /* A=cyl 1 thru 18 */
+       RDSZ(67800),    19,             /* B=cyl 19 thru 93 */
+       RDSZ(1309896),  0,              /* C=cyl 0 thru 1448 */
+       RDSZ(16272),    94,             /* D=cyl 19 thru 111 */
+       RDSZ(305552),   112,            /* E=cyl 112 thru 449 */
+       RDSZ(305552),   450,            /* F=cyl 450 thru 787 */
+       RDSZ(1224920),  94,             /* G=cyl 94 thru 1448 */
+       RDSZ(597544),   788,            /* H=cyl 788 thru 1448 */
 
 #if DEV_BSIZE == 512
 /*
 
 #if DEV_BSIZE == 512
 /*
@@ -360,19 +385,24 @@ struct rdinfo rdinfo[] = {
        rd7958B_sizes,  RD7958BID,      0,      "7958B",
        NRD7959BBPT,    NRD7959BTRK,    NRD7959BBPT * NRD7959BTRK,
        rd7959B_sizes,  RD7959BID,      0,      "7959B",
        rd7958B_sizes,  RD7958BID,      0,      "7958B",
        NRD7959BBPT,    NRD7959BTRK,    NRD7959BBPT * NRD7959BTRK,
        rd7959B_sizes,  RD7959BID,      0,      "7959B",
+       NRD2200ABPT,    NRD2200ATRK,    NRD2200ABPT * NRD2200ATRK,
+       rd2200A_sizes,  RD2200AID,      0,      "2200A",
+       NRD2203ABPT,    NRD2203ATRK,    NRD2203ABPT * NRD2203ATRK,
+       rd2203A_sizes,  RD2203AID,      0,      "2203A",
 };
 int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]);
 
 struct buf rdtab[NRD];
 };
 int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]);
 
 struct buf rdtab[NRD];
-struct buf rdbuf[NRD];
 
 
-#define        rdunit(x)       ((minor(x) >> 3) & 0xf)
+#define        rdunit(x)       (minor(x) >> 3)
 #define rdpart(x)      (minor(x) & 0x7)
 #define        rdpunit(x)      ((x) & 7)
 #define        b_cylin         b_resid
 #define        RDRETRY         5
 #define RDWAITC                1       /* min time for timeout in seconds */
 
 #define rdpart(x)      (minor(x) & 0x7)
 #define        rdpunit(x)      ((x) & 7)
 #define        b_cylin         b_resid
 #define        RDRETRY         5
 #define RDWAITC                1       /* min time for timeout in seconds */
 
+int rderrthresh = RDRETRY-1;   /* when to start reporting errors */
+
 rdinit(hd)
        register struct hp_device *hd;
 {
 rdinit(hd)
        register struct hp_device *hd;
 {
@@ -389,6 +419,11 @@ rdinit(hd)
        rs->sc_dq.dq_driver = &rddriver;
        rs->sc_info = &rdinfo[rs->sc_type];
        rs->sc_flags = RDF_ALIVE;
        rs->sc_dq.dq_driver = &rddriver;
        rs->sc_info = &rdinfo[rs->sc_type];
        rs->sc_flags = RDF_ALIVE;
+#ifdef DEBUG
+       /* always report errors */
+       if (rddebug & RDB_ERROR)
+               rderrthresh = 0;
+#endif
        return(1);
 }
 
        return(1);
 }
 
@@ -414,6 +449,10 @@ rdident(rs, hd)
         * 3. If it is a 7946, we are accessing the disk unit (0)
         */
        id = hpibid(ctlr, slave);
         * 3. If it is a 7946, we are accessing the disk unit (0)
         */
        id = hpibid(ctlr, slave);
+#ifdef DEBUG
+       if (rddebug & RDB_IDENT)
+               printf("hpibid(%d, %d) -> %x\n", ctlr, slave, id);
+#endif
        if ((id & 0x200) == 0)
                return(-1);
        for (i = 0; i < nrdinfo; i++)
        if ((id & 0x200) == 0)
                return(-1);
        for (i = 0; i < nrdinfo; i++)
@@ -442,6 +481,8 @@ rdident(rs, hd)
                        name[i] = (n & 0xf) + '0';
                        n >>= 4;
                }
                        name[i] = (n & 0xf) + '0';
                        n >>= 4;
                }
+               /* use drive characteristics to calculate xfer rate */
+               rs->sc_wpms = 1000000 * (desc.d_sectsize/2) / desc.d_blocktime;
        }
 #ifdef DEBUG
        if (rddebug & RDB_IDENT) {
        }
 #ifdef DEBUG
        if (rddebug & RDB_IDENT) {
@@ -527,29 +568,35 @@ rdreset(rs, hd)
 #endif
 }
 
 #endif
 }
 
-/*ARGSUSED*/
-rdopen(dev, flags)
+int
+rdopen(dev, flags, mode, p)
        dev_t dev;
        dev_t dev;
+       int flags, mode;
+       struct proc *p;
 {
        register int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
 
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return(ENXIO);
 {
        register int unit = rdunit(dev);
        register struct rd_softc *rs = &rd_softc[unit];
 
        if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)
                return(ENXIO);
-       if (rs->sc_hd->hp_dk >= 0)
-       dk_wpms[rs->sc_hd->hp_dk] = 60 * rs->sc_info->nbpt * DEV_BSIZE / 2;
+       if (rs->sc_hd->hp_dk >= 0) {
+               /* guess at xfer rate based on 3600 rpm (60 rps) */
+               if (rs->sc_wpms == 0)
+                       rs->sc_wpms = 60 * rs->sc_info->nbpt * DEV_BSIZE / 2;
+               dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;
+       }
        return(0);
 }
 
 rdstrategy(bp)
        register struct buf *bp;
 {
        return(0);
 }
 
 rdstrategy(bp)
        register struct buf *bp;
 {
-       register int part = rdpart(bp->b_dev);
        register int unit = rdunit(bp->b_dev);
        register int unit = rdunit(bp->b_dev);
-       register int bn, sz;
        register struct rd_softc *rs = &rd_softc[unit];
        register struct rd_softc *rs = &rd_softc[unit];
+       register struct size *pinfo = &rs->sc_info->sizes[rdpart(bp->b_dev)];
        register struct buf *dp = &rdtab[unit];
        register struct buf *dp = &rdtab[unit];
-       int s;
+       register daddr_t bn;
+       register int sz, s;
 
 #ifdef DEBUG
        if (rddebug & RDB_FOLLOW)
 
 #ifdef DEBUG
        if (rddebug & RDB_FOLLOW)
@@ -558,16 +605,21 @@ rdstrategy(bp)
                       (bp->b_flags & B_READ) ? 'R' : 'W');
 #endif
        bn = bp->b_blkno;
                       (bp->b_flags & B_READ) ? 'R' : 'W');
 #endif
        bn = bp->b_blkno;
-       sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT;
-       if (bn < 0 || bn + sz > rs->sc_info->sizes[part].nblocks) {
-               if (bn == rs->sc_info->sizes[part].nblocks) {
+       sz = howmany(bp->b_bcount, DEV_BSIZE);
+       if (bn < 0 || bn + sz > pinfo->nblocks) {
+               sz = pinfo->nblocks - bn;
+               if (sz == 0) {
                        bp->b_resid = bp->b_bcount;
                        goto done;
                }
                        bp->b_resid = bp->b_bcount;
                        goto done;
                }
-               bp->b_error = EINVAL;
-               goto bad;
+               if (sz < 0) {
+                       bp->b_error = EINVAL;
+                       bp->b_flags |= B_ERROR;
+                       goto done;
+               }
+               bp->b_bcount = dbtob(sz);
        }
        }
-       bp->b_cylin = bn / rs->sc_info->nbpc + rs->sc_info->sizes[part].cyloff;
+       bp->b_cylin = bn / rs->sc_info->nbpc + pinfo->cyloff;
        s = splbio();
        disksort(dp, bp);
        if (dp->b_active == 0) {
        s = splbio();
        disksort(dp, bp);
        if (dp->b_active == 0) {
@@ -576,8 +628,6 @@ rdstrategy(bp)
        }
        splx(s);
        return;
        }
        splx(s);
        return;
-bad:
-       bp->b_flags |= B_ERROR;
 done:
        biodone(bp);
 }
 done:
        biodone(bp);
 }
@@ -712,7 +762,7 @@ rdintr(unit)
        register struct buf *bp = rdtab[unit].b_actf;
        register struct hp_device *hp = rs->sc_hd;
        u_char stat = 13;       /* in case hpibrecv fails */
        register struct buf *bp = rdtab[unit].b_actf;
        register struct hp_device *hp = rs->sc_hd;
        u_char stat = 13;       /* in case hpibrecv fails */
-       int restart;
+       int rv, restart;
        
 #ifdef DEBUG
        if (rddebug & RDB_FOLLOW)
        
 #ifdef DEBUG
        if (rddebug & RDB_FOLLOW)
@@ -747,7 +797,8 @@ rdintr(unit)
                }
        } else
                rs->sc_flags &= ~RDF_SWAIT;
                }
        } else
                rs->sc_flags &= ~RDF_SWAIT;
-       if (!hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1) || stat) {
+       rv = hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);
+       if (rv != 1 || stat) {
 #ifdef DEBUG
                if (rddebug & RDB_ERROR)
                        printf("rdintr: recv failed or bad stat %d\n", stat);
 #ifdef DEBUG
                if (rddebug & RDB_ERROR)
                        printf("rdintr: recv failed or bad stat %d\n", stat);
@@ -830,7 +881,7 @@ rderror(unit)
        struct rd_softc *rs = &rd_softc[unit];
        register struct rd_stat *sp;
        struct buf *bp;
        struct rd_softc *rs = &rd_softc[unit];
        register struct rd_stat *sp;
        struct buf *bp;
-       daddr_t bn, pbn;
+       daddr_t hwbn, pbn;
 
        if (rdstatus(rs)) {
 #ifdef DEBUG
 
        if (rdstatus(rs)) {
 #ifdef DEBUG
@@ -865,21 +916,29 @@ rderror(unit)
                timeout(rdrestart, unit, rdtimo*hz);
                return(0);
        }
                timeout(rdrestart, unit, rdtimo*hz);
                return(0);
        }
-       bp = rdtab[unit].b_actf;
+       /*
+        * Only report error if we have reached the error reporting
+        * threshhold.  By default, this will only report after the
+        * retry limit has been exceeded.
+        */
+       if (rdtab[unit].b_errcnt < rderrthresh)
+               return(1);
+
        /*
         * First conjure up the block number at which the error occured.
         * Note that not all errors report a block number, in that case
         * we just use b_blkno.
         */
        /*
         * First conjure up the block number at which the error occured.
         * Note that not all errors report a block number, in that case
         * we just use b_blkno.
         */
-       pbn = RDSTOB(rs->sc_info->nbpc *
-                    rs->sc_info->sizes[rdpart(bp->b_dev)].cyloff);
+       bp = rdtab[unit].b_actf;
+       pbn = rs->sc_info->nbpc *
+               rs->sc_info->sizes[rdpart(bp->b_dev)].cyloff;
        if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
            (sp->c_ief & IEF_RRMASK)) {
        if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
            (sp->c_ief & IEF_RRMASK)) {
-               bn = pbn + bp->b_blkno;
+               hwbn = RDBTOS(pbn + bp->b_blkno);
                pbn = bp->b_blkno;
        } else {
                pbn = bp->b_blkno;
        } else {
-               bn = RDSTOB(sp->c_blk);
-               pbn = bn - pbn;
+               hwbn = sp->c_blk;
+               pbn = RDSTOB(hwbn) - pbn;
        }
        /*
         * Now output a generic message suitable for badsect.
        }
        /*
         * Now output a generic message suitable for badsect.
@@ -904,7 +963,7 @@ rderror(unit)
                rdprinterr("fault", sp->c_fef, err_fault);
                rdprinterr("access", sp->c_aef, err_access);
                rdprinterr("info", sp->c_ief, err_info);
                rdprinterr("fault", sp->c_fef, err_fault);
                rdprinterr("access", sp->c_aef, err_access);
                rdprinterr("info", sp->c_ief, err_info);
-               printf("    block: %d, P1-P10: ", bn);
+               printf("    block: %d, P1-P10: ", hwbn);
                printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
                printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
                printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
                printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));
                printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));
                printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));
@@ -929,34 +988,40 @@ rderror(unit)
        return(1);
 }
 
        return(1);
 }
 
-rdread(dev, uio)
+int
+rdread(dev, uio, flags)
        dev_t dev;
        struct uio *uio;
        dev_t dev;
        struct uio *uio;
+       int flags;
 {
        register int unit = rdunit(dev);
 
 {
        register int unit = rdunit(dev);
 
-       return(physio(rdstrategy, &rdbuf[unit], dev, B_READ, minphys, uio));
+       return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
 }
 
 }
 
-rdwrite(dev, uio)
+int
+rdwrite(dev, uio, flags)
        dev_t dev;
        struct uio *uio;
        dev_t dev;
        struct uio *uio;
+       int flags;
 {
        register int unit = rdunit(dev);
 
 {
        register int unit = rdunit(dev);
 
-       return(physio(rdstrategy, &rdbuf[unit], dev, B_WRITE, minphys, uio));
+       return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
 }
 
 }
 
-/*ARGSUSED*/
-rdioctl(dev, cmd, data, flag)
+int
+rdioctl(dev, cmd, data, flag, p)
        dev_t dev;
        int cmd;
        caddr_t data;
        int flag;
        dev_t dev;
        int cmd;
        caddr_t data;
        int flag;
+       struct proc *p;
 {
        return(EINVAL);
 }
 
 {
        return(EINVAL);
 }
 
+int
 rdsize(dev)
        dev_t dev;
 {
 rdsize(dev)
        dev_t dev;
 {
@@ -988,13 +1053,10 @@ rdprinterr(str, err, tab)
 }
 #endif
 
 }
 #endif
 
-#include "machine/pte.h"
-#include "machine/vmparam.h"
-#include "../h/vmmac.h"
-
 /*
  * Non-interrupt driven, non-dma dump routine.
  */
 /*
  * Non-interrupt driven, non-dma dump routine.
  */
+int
 rddump(dev)
        dev_t dev;
 {
 rddump(dev)
        dev_t dev;
 {
@@ -1003,10 +1065,13 @@ rddump(dev)
        register struct rd_softc *rs = &rd_softc[unit];
        register struct hp_device *hp = rs->sc_hd;
        register daddr_t baddr;
        register struct rd_softc *rs = &rd_softc[unit];
        register struct hp_device *hp = rs->sc_hd;
        register daddr_t baddr;
-       register int maddr;
-       register int pages, i;
+       register int maddr, pages, i;
        char stat;
        extern int lowram, dumpsize;
        char stat;
        extern int lowram, dumpsize;
+#ifdef DEBUG
+       extern int pmapdebug;
+       pmapdebug = 0;
+#endif
 
        pages = dumpsize;
 #ifdef DEBUG
 
        pages = dumpsize;
 #ifdef DEBUG
@@ -1066,7 +1131,8 @@ rddump(dev)
 #endif
                        return (EIO);
                }
 #endif
                        return (EIO);
                }
-               mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V);
+               pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,
+                   VM_PROT_READ, TRUE);
                hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
                if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
 #ifdef DEBUG
                hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);
                if (hpibswait(hp->hp_ctlr, hp->hp_slave)) {
 #ifdef DEBUG