default ncylinders to 1 for disklabel
[unix-history] / usr / src / sys / hp300 / dev / st.c
index 54dddf8..7ff55ba 100644 (file)
@@ -9,9 +9,9 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- * from: Utah $Hdr: st.c 1.8 90/10/14$
+ * from: Utah $Hdr: st.c 1.11 92/01/21$
  *
  *
- *      @(#)st.c       7.3 (Berkeley) %G%
+ *      @(#)st.c       7.9 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
 #include "st.h"
 #if NST > 0
 
 #include "st.h"
 #if NST > 0
 
-#include "param.h"
-#include "systm.h"
-#include "buf.h"
-#include "scsireg.h"
-#include "file.h"
-#include "tty.h"
-#include "proc.h"
-#include "mtio.h"
-#include "ioctl.h"
-#include "kernel.h"
-#include "tprintf.h"
-
-#include "device.h"
-#include "stvar.h"
-
-#define ADD_DELAY
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/mtio.h>
+#include <sys/kernel.h>
+#include <sys/tprintf.h>
+
+#include <hp/dev/device.h>
+#include <hp300/dev/scsireg.h>
+#include <hp300/dev/stvar.h>
 
 extern int scsi_test_unit_rdy();
 extern int scsi_request_sense();
 
 extern int scsi_test_unit_rdy();
 extern int scsi_request_sense();
@@ -168,8 +166,7 @@ int st_dmaoddretry = 0;
  * Use 0x400 for 1k (best capacity) fixed length records.
  * In st_open, if minor bit 4 set then 1k records are used.
  * If st_exblken is set to anything other then 0 we are in fixed length mode.
  * Use 0x400 for 1k (best capacity) fixed length records.
  * In st_open, if minor bit 4 set then 1k records are used.
  * If st_exblken is set to anything other then 0 we are in fixed length mode.
- * Minor bit 4 overrides any setting of st_exblklen.
- * 
+ * Minor bit 5 requests 1K fixed-length, overriding any setting of st_exblklen.
  */
 int st_exblklen = 0;
 
  */
 int st_exblklen = 0;
 
@@ -201,7 +198,10 @@ stinit(hd)
        register struct hp_device *hd;
 {
        register struct st_softc *sc = &st_softc[hd->hp_unit];
        register struct hp_device *hd;
 {
        register struct st_softc *sc = &st_softc[hd->hp_unit];
+       register struct buf *bp;
 
 
+       for (bp = sttab; bp < &sttab[NST]; bp++)
+               bp->b_actb = &bp->b_actf;
        sc->sc_hd = hd;
        sc->sc_punit = stpunit(hd->hp_flags);
        sc->sc_type = stident(sc, hd);
        sc->sc_hd = hd;
        sc->sc_punit = stpunit(hd->hp_flags);
        sc->sc_type = stident(sc, hd);
@@ -224,9 +224,7 @@ stident(sc, hd)
        int ctlr, slave;
        int i, stat, inqlen;
        char idstr[32];
        int ctlr, slave;
        int i, stat, inqlen;
        char idstr[32];
-#ifdef ADD_DELAY
        static int havest = 0;
        static int havest = 0;
-#endif
        struct st_inquiry {
                struct  scsi_inquiry inqbuf;
                struct  exb_inquiry exb_inquiry;
        struct st_inquiry {
                struct  scsi_inquiry inqbuf;
                struct  exb_inquiry exb_inquiry;
@@ -251,11 +249,25 @@ stident(sc, hd)
        if (stat == -1)
                goto failed;
 
        if (stat == -1)
                goto failed;
 
-       if (st_inqbuf.inqbuf.type != 0x01 ||  /* sequential access device */
+       if ((st_inqbuf.inqbuf.type != 0x01 ||  /* sequential access device */
            st_inqbuf.inqbuf.qual != 0x80 ||  /* removable media */
            (st_inqbuf.inqbuf.version != 0x01 && /* current ANSI SCSI spec */
            st_inqbuf.inqbuf.qual != 0x80 ||  /* removable media */
            (st_inqbuf.inqbuf.version != 0x01 && /* current ANSI SCSI spec */
-            st_inqbuf.inqbuf.version != 0x02))  /* 0x02 is for HP DAT */
+            st_inqbuf.inqbuf.version != 0x02)) /* 0x02 is for HP DAT */
+           &&
+           (st_inqbuf.inqbuf.type != 0x01 ||   /* M4 ??! */
+            /*
+             * the M4 is a little too smart (ass?) for its own good:
+             * qual codes:
+             * 0x80: you can take the tape out (unit not online)
+             * 0xf8: online and at 6250bpi
+             * 0xf9: online and at 1600bpi
+             */
+            st_inqbuf.inqbuf.version != 0x09)) /* M4 tape */
+{
+printf("st: wrong specs: type %x qual %x version %d\n", st_inqbuf.inqbuf.type,
+st_inqbuf.inqbuf.qual, st_inqbuf.inqbuf.version);
                goto failed;
                goto failed;
+}
 
        /* now get additonal info */
        inqlen = 0x05 + st_inqbuf.inqbuf.len;
 
        /* now get additonal info */
        inqlen = 0x05 + st_inqbuf.inqbuf.len;
@@ -317,6 +329,12 @@ stident(sc, hd)
                sc->sc_datalen[CMD_INQUIRY] = 36;
                sc->sc_datalen[CMD_MODE_SELECT] = 12;
                sc->sc_datalen[CMD_MODE_SENSE] = 12;
                sc->sc_datalen[CMD_INQUIRY] = 36;
                sc->sc_datalen[CMD_MODE_SELECT] = 12;
                sc->sc_datalen[CMD_MODE_SENSE] = 12;
+       } else if (bcmp("123107 SCSI", &idstr[8], 11) == 0) {
+               sc->sc_tapeid = MT_ISMFOUR;
+               sc->sc_datalen[CMD_REQUEST_SENSE] = 8;
+               sc->sc_datalen[CMD_INQUIRY] = 5;
+               sc->sc_datalen[CMD_MODE_SELECT] = 12;
+               sc->sc_datalen[CMD_MODE_SENSE] = 12;
        } else {
                if (idstr[8] == '\0')
                        printf("st%d: No ID, assuming Archive\n", hd->hp_unit);
        } else {
                if (idstr[8] == '\0')
                        printf("st%d: No ID, assuming Archive\n", hd->hp_unit);
@@ -335,13 +353,11 @@ stident(sc, hd)
        stxsense(ctlr, slave, unit, sc);
 
        scsi_delay(0);
        stxsense(ctlr, slave, unit, sc);
 
        scsi_delay(0);
-#ifdef ADD_DELAY
        /* XXX if we have a tape, we must up the delays in the HA driver */
        if (!havest) {
                havest = 1;
                scsi_delay(20000);
        }
        /* XXX if we have a tape, we must up the delays in the HA driver */
        if (!havest) {
                havest = 1;
                scsi_delay(20000);
        }
-#endif
        return(st_inqbuf.inqbuf.type);
 failed:
        scsi_delay(0);
        return(st_inqbuf.inqbuf.type);
 failed:
        scsi_delay(0);
@@ -361,6 +377,7 @@ stopen(dev, flag, type, p)
        struct mode_select_data msd;
        struct mode_sense mode;
        int modlen;
        struct mode_select_data msd;
        struct mode_sense mode;
        int modlen;
+       int error;
        static struct scsi_fmt_cdb modsel = {
                6,
                CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0
        static struct scsi_fmt_cdb modsel = {
                6,
                CMD_MODE_SELECT, 0, 0, 0, sizeof(msd), 0
@@ -416,6 +433,9 @@ stopen(dev, flag, type, p)
        case MT_ISPYTHON:
                sc->sc_blklen = 512;
                break;
        case MT_ISPYTHON:
                sc->sc_blklen = 512;
                break;
+       case MT_ISMFOUR:
+               sc->sc_blklen = 0;
+               break;
        default:
                if ((mode.md.blklen2 << 16 |
                     mode.md.blklen1 << 8 |
        default:
                if ((mode.md.blklen2 << 16 |
                     mode.md.blklen1 << 8 |
@@ -443,6 +463,10 @@ stopen(dev, flag, type, p)
        msd.blklen1 = (sc->sc_blklen >> 8) & 0xff;
        msd.blklen0 = sc->sc_blklen & 0xff;
 
        msd.blklen1 = (sc->sc_blklen >> 8) & 0xff;
        msd.blklen0 = sc->sc_blklen & 0xff;
 
+       /*
+        * Do we have any density problems?
+        */
+
        switch (sc->sc_tapeid) {
        case MT_ISAR:
                if (minor(dev) & STDEV_HIDENSITY)
        switch (sc->sc_tapeid) {
        case MT_ISAR:
                if (minor(dev) & STDEV_HIDENSITY)
@@ -471,6 +495,8 @@ stopen(dev, flag, type, p)
                if (minor(dev) & STDEV_HIDENSITY)
                        uprintf("Only one density supported\n");
                break;
                if (minor(dev) & STDEV_HIDENSITY)
                        uprintf("Only one density supported\n");
                break;
+       case MT_ISMFOUR:
+               break;          /* XXX could do density select? */
        default:
                uprintf("Unsupported drive\n");
                return(EIO);
        default:
                uprintf("Unsupported drive\n");
                return(EIO);
@@ -518,7 +544,9 @@ retryselect:
                        uprintf("SCSI bus timeout\n");
                        return(EBUSY);
                }
                        uprintf("SCSI bus timeout\n");
                        return(EBUSY);
                }
-               sleep((caddr_t)&lbolt, PZERO+1);
+               if (error = tsleep((caddr_t)&lbolt, PZERO | PCATCH, 
+                   "st_scsiwait", 0))
+                       return (error);
                goto retryselect;
        }
 
                goto retryselect;
        }
 
@@ -543,6 +571,7 @@ retryselect:
                        else 
                                prtkey(UNIT(dev), sc);
                        break;
                        else 
                                prtkey(UNIT(dev), sc);
                        break;
+               case MT_ISMFOUR:
                case MT_ISAR:
                        if (xsense->sc_xsense.key & XSK_UNTATTEN)
                                stat = scsi_test_unit_rdy(ctlr, slave, unit);
                case MT_ISAR:
                        if (xsense->sc_xsense.key & XSK_UNTATTEN)
                                stat = scsi_test_unit_rdy(ctlr, slave, unit);
@@ -637,10 +666,14 @@ stclose(dev, flag)
 
        if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
                /*
 
        if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
                /*
-                * XXX driver only supports cartridge tapes.
                 * Cartridge tapes don't do double EOFs on EOT.
                 * Cartridge tapes don't do double EOFs on EOT.
+                * We assume that variable-block devices use double EOF.
                 */
                stcommand(dev, MTWEOF, 1); 
                 */
                stcommand(dev, MTWEOF, 1); 
+               if (sc->sc_blklen == 0) {
+                       stcommand(dev, MTWEOF, 1); 
+                       stcommand(dev, MTBSR, 1); 
+               }
                hit++;
        }
        if ((minor(dev) & STDEV_NOREWIND) == 0) {
                hit++;
        }
        if ((minor(dev) & STDEV_NOREWIND) == 0) {
@@ -669,13 +702,11 @@ ststrategy(bp)
 
        unit = UNIT(bp->b_dev);
        dp = &sttab[unit];
 
        unit = UNIT(bp->b_dev);
        dp = &sttab[unit];
-       bp->av_forw = NULL;
+       bp->b_actf = NULL;
        s = splbio();
        s = splbio();
-       if (dp->b_actf == NULL)
-               dp->b_actf = bp;
-       else
-               dp->b_actl->av_forw = bp;
-       dp->b_actl = bp;
+       bp->b_actb = dp->b_actb;
+       *dp->b_actb = bp;
+       dp->b_actb = &bp->b_actf;
        if (dp->b_active == 0) {
                dp->b_active = 1;
                stustart(unit);
        if (dp->b_active == 0) {
                dp->b_active = 1;
                stustart(unit);
@@ -785,8 +816,14 @@ stfinish(unit, sc, bp)
        struct st_softc *sc;
        struct buf *bp;
 {
        struct st_softc *sc;
        struct buf *bp;
 {
+       register struct buf *dp;
+
        sttab[unit].b_errcnt = 0;
        sttab[unit].b_errcnt = 0;
-       sttab[unit].b_actf = bp->b_actf;
+       if (dp = bp->b_actf)
+               dp->b_actb = bp->b_actb;
+       else
+               sttab[unit].b_actb = bp->b_actb;
+       *bp->b_actb = dp;
        iodone(bp);
        scsifree(&sc->sc_dq);
        if (sttab[unit].b_actf)
        iodone(bp);
        scsifree(&sc->sc_dq);
        if (sttab[unit].b_actf)
@@ -943,7 +980,10 @@ stintr(unit, stat)
                        sc->sc_filepos++;
                        break;
                }
                        sc->sc_filepos++;
                        break;
                }
-               if (xp->sc_xsense.key) {
+               if (xp->sc_xsense.key != XSK_NOSENCE
+                   && xp->sc_xsense.key != XSK_NOTUSED1
+                   && xp->sc_xsense.key != XSK_NOTUSEDC
+                   && xp->sc_xsense.key != XSK_NOTUSEDE) {
                        sterror(unit, sc, stat);
                        bp->b_flags |= B_ERROR;
                        bp->b_error = EIO;
                        sterror(unit, sc, stat);
                        bp->b_flags |= B_ERROR;
                        bp->b_error = EIO;
@@ -963,7 +1003,7 @@ stintr(unit, stat)
                        }
                        /*
                         * Variable length but read more than requested,
                        }
                        /*
                         * Variable length but read more than requested,
-                        * an error.
+                        * an error.  (XXX ??? wrong for 9 track?)
                         */
                        if (bp->b_resid < 0) {
                                bp->b_resid = 0;
                         */
                        if (bp->b_resid < 0) {
                                bp->b_resid = 0;
@@ -975,7 +1015,7 @@ stintr(unit, stat)
                         * Variable length and odd, may require special
                         * handling.
                         */
                         * Variable length and odd, may require special
                         * handling.
                         */
-                       if (bp->b_resid & 1 && sc->sc_tapeid != MT_ISAR) {
+                       if (bp->b_resid & 1 && (sc->sc_tapeid != MT_ISAR)) {
                                /*
                                 * Normal behavior, treat as an error.
                                 */
                                /*
                                 * Normal behavior, treat as an error.
                                 */