BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / hp300 / dev / sd.c
index a1d1c09..3876118 100644 (file)
@@ -5,9 +5,35 @@
  * This code is derived from software contributed to Berkeley by
  * Van Jacobson of Lawrence Berkeley Laboratory.
  *
  * This code is derived from software contributed to Berkeley by
  * Van Jacobson of Lawrence Berkeley Laboratory.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)sd.c        7.4 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)sd.c        7.8 (Berkeley) 6/9/91
  */
 
 /*
  */
 
 /*
 #if NSD > 0
 
 #ifndef lint
 #if NSD > 0
 
 #ifndef lint
-static char rcsid[] = "$Header: sd.c,v 1.3 90/10/10 14:55:10 mike Exp $";
+static char rcsid[] = "$Header: sd.c,v 1.15 91/04/24 11:54:30 mike Exp $";
 #endif
 
 #include "sys/param.h"
 #include "sys/systm.h"
 #include "sys/buf.h"
 #endif
 
 #include "sys/param.h"
 #include "sys/systm.h"
 #include "sys/buf.h"
-#include "sys/errno.h"
 #include "sys/dkstat.h"
 #include "sys/disklabel.h"
 #include "sys/dkstat.h"
 #include "sys/disklabel.h"
-#include "device.h"
 #include "sys/malloc.h"
 #include "sys/malloc.h"
-#include "scsireg.h"
-
-#include "sys/user.h"
 #include "sys/proc.h"
 #include "sys/proc.h"
-#include "sys/uio.h"
 
 
+#include "device.h"
+#include "scsireg.h"
 #include "vm/vm_param.h"
 #include "vm/vm_param.h"
+#include "vm/lock.h"
+#include "vm/vm_statistics.h"
 #include "vm/pmap.h"
 #include "vm/vm_prot.h"
 
 #include "vm/pmap.h"
 #include "vm/vm_prot.h"
 
@@ -48,12 +72,9 @@ extern int scsiustart();
 extern int scsigo();
 extern void scsifree();
 extern void scsireset();
 extern int scsigo();
 extern void scsifree();
 extern void scsireset();
+extern void scsi_delay();
 
 
-extern void printf();
-extern void bcopy();
 extern void disksort();
 extern void disksort();
-extern int splbio();
-extern void splx();
 extern void biodone();
 extern int physio();
 extern void TBIS();
 extern void biodone();
 extern int physio();
 extern void TBIS();
@@ -124,14 +145,13 @@ struct sdstats {
 } sdstats[NSD];
 
 struct buf sdtab[NSD];
 } sdstats[NSD];
 
 struct buf sdtab[NSD];
-struct buf sdbuf[NSD];
 struct scsi_fmt_cdb sdcmd[NSD];
 struct scsi_fmt_sense sdsense[NSD];
 
 static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
 static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
 
 struct scsi_fmt_cdb sdcmd[NSD];
 struct scsi_fmt_sense sdsense[NSD];
 
 static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
 static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
 
-#define        sdunit(x)       ((minor(x) >> 3) & 0x7)
+#define        sdunit(x)       (minor(x) >> 3)
 #define sdpart(x)      (minor(x) & 0x7)
 #define        sdpunit(x)      ((x) & 7)
 #define        b_cylin         b_resid
 #define sdpart(x)      (minor(x) & 0x7)
 #define        sdpunit(x)      ((x) & 7)
 #define        b_cylin         b_resid
@@ -184,11 +204,13 @@ sdident(sc, hd)
        register int ctlr, slave;
        register int i;
        register int tries = 10;
        register int ctlr, slave;
        register int i;
        register int tries = 10;
+       char idstr[32];
        int ismo = 0;
 
        ctlr = hd->hp_ctlr;
        slave = hd->hp_slave;
        unit = sc->sc_punit;
        int ismo = 0;
 
        ctlr = hd->hp_ctlr;
        slave = hd->hp_slave;
        unit = sc->sc_punit;
+       scsi_delay(-1);
 
        /*
         * See if unit exists and is a disk then read block size & nblocks.
 
        /*
         * See if unit exists and is a disk then read block size & nblocks.
@@ -198,7 +220,7 @@ sdident(sc, hd)
                        if (ismo)
                                break;
                        /* doesn't exist or not a CCS device */
                        if (ismo)
                                break;
                        /* doesn't exist or not a CCS device */
-                       return (-1);
+                       goto failed;
                }
                if (i == STS_CHECKCOND) {
                        u_char sensebuf[128];
                }
                if (i == STS_CHECKCOND) {
                        u_char sensebuf[128];
@@ -229,7 +251,7 @@ sdident(sc, hd)
         */
        if (scsi_immed_command(ctlr, slave, unit, &inq,
                               (u_char *)&inqbuf, sizeof(inqbuf), B_READ))
         */
        if (scsi_immed_command(ctlr, slave, unit, &inq,
                               (u_char *)&inqbuf, sizeof(inqbuf), B_READ))
-               return(-1);
+               goto failed;
        switch (inqbuf.type) {
        case 0:         /* disk */
        case 4:         /* WORM */
        switch (inqbuf.type) {
        case 0:         /* disk */
        case 4:         /* WORM */
@@ -237,29 +259,39 @@ sdident(sc, hd)
        case 7:         /* Magneto-optical */
                break;
        default:        /* not a disk */
        case 7:         /* Magneto-optical */
                break;
        default:        /* not a disk */
-               return (-1);
+               goto failed;
        }
        /*
        }
        /*
-        * XXX determine if this is an HP MO drive.
+        * Get a usable id string
         */
         */
-       {
-               u_long *id = (u_long *)&inqbuf;
-
-               ismo = (id[2] == 0x48502020 &&  /* "HP  " */
-                       id[3] == 0x20202020 &&  /* "    " */
-                       id[4] == 0x53363330 &&  /* "S630" */
-                       id[5] == 0x302e3635 &&  /* "0.65" */
-                       id[6] == 0x30412020);   /* "0A  " */
+       if (inqbuf.version != 1) {
+               bcopy("UNKNOWN", &idstr[0], 8);
+               bcopy("DRIVE TYPE", &idstr[8], 11);
+       } else {
+               bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
+               for (i = 27; i > 23; --i)
+                       if (idstr[i] != ' ')
+                               break;
+               idstr[i+1] = 0;
+               for (i = 23; i > 7; --i)
+                       if (idstr[i] != ' ')
+                               break;
+               idstr[i+1] = 0;
+               for (i = 7; i >= 0; --i)
+                       if (idstr[i] != ' ')
+                               break;
+               idstr[i+1] = 0;
        }
        i = scsi_immed_command(ctlr, slave, unit, &cap,
                               (u_char *)&capbuf, sizeof(capbuf), B_READ);
        if (i) {
        }
        i = scsi_immed_command(ctlr, slave, unit, &cap,
                               (u_char *)&capbuf, sizeof(capbuf), B_READ);
        if (i) {
+               if (i != STS_CHECKCOND ||
+                   bcmp(&idstr[0], "HP", 3) ||
+                   bcmp(&idstr[8], "S6300.650A", 11))
+                       goto failed;
                /* XXX unformatted or non-existant MO media; fake it */
                /* XXX unformatted or non-existant MO media; fake it */
-               if (i == STS_CHECKCOND && ismo) {
-                       sc->sc_blks = 318664;
-                       sc->sc_blksize = 1024;
-               } else
-                       return(-1);
+               sc->sc_blks = 318664;
+               sc->sc_blksize = 1024;
        } else {
                sc->sc_blks = *(u_int *)&capbuf[0];
                sc->sc_blksize = *(int *)&capbuf[4];
        } else {
                sc->sc_blks = *(u_int *)&capbuf[0];
                sc->sc_blksize = *(int *)&capbuf[4];
@@ -270,38 +302,26 @@ sdident(sc, hd)
        if (inqbuf.version != 1)
                printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit,
                        inqbuf.type, inqbuf.qual, inqbuf.version);
        if (inqbuf.version != 1)
                printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit,
                        inqbuf.type, inqbuf.qual, inqbuf.version);
-       else {
-               char idstr[32];
-
-               bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
-               for (i = 27; i > 23; --i)
-                       if (idstr[i] != ' ')
-                               break;
-               idstr[i+1] = 0;
-               for (i = 23; i > 7; --i)
-                       if (idstr[i] != ' ')
-                               break;
-               idstr[i+1] = 0;
-               for (i = 7; i >= 0; --i)
-                       if (idstr[i] != ' ')
-                               break;
-               idstr[i+1] = 0;
+       else
                printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
                        &idstr[24]);
                printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
                        &idstr[24]);
-       }
        printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
        if (sc->sc_blksize != DEV_BSIZE) {
                if (sc->sc_blksize < DEV_BSIZE) {
                        printf("sd%d: need %d byte blocks - drive ignored\n",
                                unit, DEV_BSIZE);
        printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
        if (sc->sc_blksize != DEV_BSIZE) {
                if (sc->sc_blksize < DEV_BSIZE) {
                        printf("sd%d: need %d byte blocks - drive ignored\n",
                                unit, DEV_BSIZE);
-                       return (-1);
+                       goto failed;
                }
                for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
                        ++sc->sc_bshift;
                sc->sc_blks <<= sc->sc_bshift;
        }
        sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);        /* XXX */
                }
                for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
                        ++sc->sc_bshift;
                sc->sc_blks <<= sc->sc_bshift;
        }
        sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);        /* XXX */
+       scsi_delay(0);
        return(inqbuf.type);
        return(inqbuf.type);
+failed:
+       scsi_delay(0);
+       return(-1);
 }
 
 int
 }
 
 int
@@ -371,16 +391,17 @@ sdreset(sc, hd)
 }
 
 int
 }
 
 int
-sdopen(dev, flags)
+sdopen(dev, flags, mode, p)
        dev_t dev;
        dev_t dev;
-       int flags;
+       int flags, mode;
+       struct proc *p;
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
 
        if (unit >= NSD)
                return(ENXIO);
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
 
        if (unit >= NSD)
                return(ENXIO);
-       if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(u.u_cred, &u.u_acflag))
+       if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
                return(ENXIO);
 
        if (sc->sc_hd->hp_dk >= 0)
                return(ENXIO);
 
        if (sc->sc_hd->hp_dk >= 0)
@@ -409,7 +430,7 @@ sdlblkstrat(bp, bsize)
        register caddr_t addr;
 
        bzero((caddr_t)cbp, sizeof(*cbp));
        register caddr_t addr;
 
        bzero((caddr_t)cbp, sizeof(*cbp));
-       cbp->b_proc = u.u_procp;
+       cbp->b_proc = curproc;          /* XXX */
        cbp->b_dev = bp->b_dev;
        bn = bp->b_blkno;
        resid = bp->b_bcount;
        cbp->b_dev = bp->b_dev;
        bn = bp->b_blkno;
        resid = bp->b_bcount;
@@ -498,7 +519,7 @@ sdstrategy(bp)
        register int sz, s;
 
        if (sc->sc_format_pid) {
        register int sz, s;
 
        if (sc->sc_format_pid) {
-               if (sc->sc_format_pid != u.u_procp->p_pid) {
+               if (sc->sc_format_pid != curproc->p_pid) {      /* XXX */
                        bp->b_error = EPERM;
                        bp->b_flags |= B_ERROR;
                        goto done;
                        bp->b_error = EPERM;
                        bp->b_flags |= B_ERROR;
                        goto done;
@@ -550,13 +571,19 @@ sdustart(unit)
                sdstart(unit);
 }
 
                sdstart(unit);
 }
 
+/*
+ * Return:
+ *     0       if not really an error
+ *     <0      if we should do a retry
+ *     >0      if a fatal error
+ */
 static int
 sderror(unit, sc, hp, stat)
        int unit, stat;
        register struct sd_softc *sc;
        register struct hp_device *hp;
 {
 static int
 sderror(unit, sc, hp, stat)
        int unit, stat;
        register struct sd_softc *sc;
        register struct hp_device *hp;
 {
-       int retry = 0;
+       int cond = 1;
 
        sdsense[unit].status = stat;
        if (stat & STS_CHECKCOND) {
 
        sdsense[unit].status = stat;
        if (stat & STS_CHECKCOND) {
@@ -572,13 +599,20 @@ sderror(unit, sc, hp, stat)
                        printf(", key %d", sp->key);
                        if (sp->valid)
                                printf(", blk %d", *(int *)&sp->info1);
                        printf(", key %d", sp->key);
                        if (sp->valid)
                                printf(", blk %d", *(int *)&sp->info1);
-                       /* no sense or recovered error, try again */
-                       if (sp->key == 0 || sp->key == 1)
-                               retry = 1;
+                       switch (sp->key) {
+                       /* no sense, try again */
+                       case 0:
+                               cond = -1;
+                               break;
+                       /* recovered error, not a problem */
+                       case 1:
+                               cond = 0;
+                               break;
+                       }
                }
                printf("\n");
        }
                }
                printf("\n");
        }
-       return(retry);
+       return(cond);
 }
 
 static void
 }
 
 static void
@@ -684,7 +718,7 @@ sdintr(unit, stat)
        register struct sd_softc *sc = &sd_softc[unit];
        register struct buf *bp = sdtab[unit].b_actf;
        register struct hp_device *hp = sc->sc_hd;
        register struct sd_softc *sc = &sd_softc[unit];
        register struct buf *bp = sdtab[unit].b_actf;
        register struct hp_device *hp = sc->sc_hd;
-       int retry;
+       int cond;
        
        if (bp == NULL) {
                printf("sd%d: bp == NULL\n", unit);
        
        if (bp == NULL) {
                printf("sd%d: bp == NULL\n", unit);
@@ -698,53 +732,63 @@ sdintr(unit, stat)
                        printf("sd%d: sdintr: bad scsi status 0x%x\n",
                                unit, stat);
 #endif
                        printf("sd%d: sdintr: bad scsi status 0x%x\n",
                                unit, stat);
 #endif
-               retry = sderror(unit, sc, hp, stat);
-               if (retry && sdtab[unit].b_errcnt++ < SDRETRY) {
-                       printf("sd%d: retry #%d\n",
-                              unit, sdtab[unit].b_errcnt);
-                       sdstart(unit);
-                       return;
+               cond = sderror(unit, sc, hp, stat);
+               if (cond) {
+                       if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
+#ifdef DEBUG
+                               if (sddebug & SDB_ERROR)
+                                       printf("sd%d: retry #%d\n",
+                                              unit, sdtab[unit].b_errcnt);
+#endif
+                               sdstart(unit);
+                               return;
+                       }
+                       bp->b_flags |= B_ERROR;
+                       bp->b_error = EIO;
                }
                }
-               bp->b_flags |= B_ERROR;
-               bp->b_error = EIO;
        }
        sdfinish(unit, sc, bp);
 }
 
 int
        }
        sdfinish(unit, sc, bp);
 }
 
 int
-sdread(dev, uio)
+sdread(dev, uio, flags)
        dev_t dev;
        struct uio *uio;
        dev_t dev;
        struct uio *uio;
+       int flags;
 {
        register int unit = sdunit(dev);
        register int pid;
 
 {
        register int unit = sdunit(dev);
        register int pid;
 
-       if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid)
+       if ((pid = sd_softc[unit].sc_format_pid) &&
+           pid != uio->uio_procp->p_pid)
                return (EPERM);
                
                return (EPERM);
                
-       return(physio(sdstrategy, &sdbuf[unit], dev, B_READ, minphys, uio));
+       return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
 }
 
 int
 }
 
 int
-sdwrite(dev, uio)
+sdwrite(dev, uio, flags)
        dev_t dev;
        struct uio *uio;
        dev_t dev;
        struct uio *uio;
+       int flags;
 {
        register int unit = sdunit(dev);
        register int pid;
 
 {
        register int unit = sdunit(dev);
        register int pid;
 
-       if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid)
+       if ((pid = sd_softc[unit].sc_format_pid) &&
+           pid != uio->uio_procp->p_pid)
                return (EPERM);
                
                return (EPERM);
                
-       return(physio(sdstrategy, &sdbuf[unit], dev, B_WRITE, minphys, uio));
+       return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
 }
 
 int
 }
 
 int
-sdioctl(dev, cmd, data, flag)
+sdioctl(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;
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
 {
        register int unit = sdunit(dev);
        register struct sd_softc *sc = &sd_softc[unit];
@@ -755,13 +799,13 @@ sdioctl(dev, cmd, data, flag)
 
        case SDIOCSFORMAT:
                /* take this device into or out of "format" mode */
 
        case SDIOCSFORMAT:
                /* take this device into or out of "format" mode */
-               if (suser(u.u_cred, &u.u_acflag))
+               if (suser(p->p_ucred, &p->p_acflag))
                        return(EPERM);
 
                if (*(int *)data) {
                        if (sc->sc_format_pid)
                                return (EPERM);
                        return(EPERM);
 
                if (*(int *)data) {
                        if (sc->sc_format_pid)
                                return (EPERM);
-                       sc->sc_format_pid = u.u_procp->p_pid;
+                       sc->sc_format_pid = p->p_pid;
                } else
                        sc->sc_format_pid = 0;
                return (0);
                } else
                        sc->sc_format_pid = 0;
                return (0);
@@ -776,7 +820,7 @@ sdioctl(dev, cmd, data, flag)
                 * Save what user gave us as SCSI cdb to use with next
                 * read or write to the char device.
                 */
                 * Save what user gave us as SCSI cdb to use with next
                 * read or write to the char device.
                 */
-               if (sc->sc_format_pid != u.u_procp->p_pid)
+               if (sc->sc_format_pid != p->p_pid)
                        return (EPERM);
                if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
                        return (EINVAL);
                        return (EPERM);
                if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
                        return (EINVAL);