home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / dev / ct.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  19.9 KB  |  857 lines

  1. /*
  2.  * Copyright (c) 1982, 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)ct.c    7.3 (Berkeley) 5/4/91
  34.  */
  35.  
  36. #include "ct.h"
  37. #if NCT > 0
  38. /*
  39.  * CS80 cartridge tape driver (9144, 88140, 9145)
  40.  *
  41.  * Reminder:
  42.  *    C_CC bit (character count option) when used in the CS/80 command
  43.  *    'set options' will cause the tape not to stream.
  44.  *
  45.  * TODO:
  46.  *    make filesystem compatible
  47.  *    make block mode work according to mtio(4) spec. (if possible)
  48.  *    merge with cs80 disk driver
  49.  *    finish support of 9145
  50.  */
  51.  
  52. #include "param.h"
  53. #include "buf.h"
  54. #include "ioctl.h"
  55. #include "mtio.h"
  56. #include "tprintf.h"
  57. #include "proc.h"
  58.  
  59. #include "ctreg.h"
  60. #include "device.h"
  61.  
  62. /* number of eof marks to remember */
  63. #define EOFS    128
  64.  
  65. int    ctinit(), ctstart(), ctgo(), ctintr();
  66. struct    driver ctdriver = {
  67.     ctinit, "ct", ctstart, ctgo, ctintr,
  68. };
  69.  
  70. struct    ct_softc {
  71.     struct    hp_device *sc_hd;
  72.     struct    ct_iocmd sc_ioc;
  73.     struct    ct_rscmd sc_rsc;
  74.     struct    ct_stat sc_stat;
  75.     struct    ct_ssmcmd sc_ssmc;
  76.     struct    ct_srcmd sc_src;
  77.     struct    ct_soptcmd sc_soptc;
  78.     struct    ct_ulcmd sc_ul;
  79.     struct    ct_wfmcmd sc_wfm;
  80.     struct    ct_clearcmd sc_clear;
  81.     struct    buf *sc_bp;
  82.     int    sc_blkno;
  83.     int    sc_cmd;
  84.     int    sc_resid;
  85.     char    *sc_addr;
  86.     int    sc_flags;
  87.     short    sc_type;
  88.     short    sc_punit;
  89.     tpr_t    sc_tpr;
  90.     struct    devqueue sc_dq;
  91.     int    sc_eofp;
  92.     int    sc_eofs[EOFS];
  93. } ct_softc[NCT];
  94.  
  95. /* flags */
  96. #define    CTF_OPEN    0x01
  97. #define    CTF_ALIVE    0x02
  98. #define    CTF_WRT        0x04
  99. #define    CTF_CMD        0x08
  100. #define    CTF_IO        0x10
  101. #define    CTF_BEOF    0x20
  102. #define    CTF_AEOF    0x40
  103. #define    CTF_EOT        0x80
  104. #define    CTF_STATWAIT    0x100
  105. #define CTF_CANSTREAM    0x200
  106. #define    CTF_WRTTN    0x400
  107.  
  108. struct    ctinfo {
  109.     short    hwid;
  110.     short    punit;
  111.     char    *desc;
  112. } ctinfo[] = {
  113.     CT7946ID,    1,    "7946A",
  114.     CT7912PID,    1,    "7912P",
  115.     CT7914PID,    1,    "7914P",
  116.     CT9144ID,    0,    "9144",
  117.     CT9145ID,    0,    "9145",
  118. };
  119. int    nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
  120.  
  121. struct    buf cttab[NCT];
  122. struct    buf ctbuf[NCT];
  123.  
  124. #define    CT_NOREW    4
  125. #define    CT_STREAM    8
  126. #define    UNIT(x)        (minor(x) & 3)
  127. #define    ctpunit(x)    ((x) & 7)
  128.  
  129. #ifdef DEBUG
  130. int ctdebug = 0;
  131. #define CDB_FILES    0x01
  132. #define CT_BSF        0x02
  133. #endif
  134.  
  135. ctinit(hd)
  136.     register struct hp_device *hd;
  137. {
  138.     register struct ct_softc *sc = &ct_softc[hd->hp_unit];
  139.  
  140.     sc->sc_hd = hd;
  141.     sc->sc_punit = ctpunit(hd->hp_flags);
  142.     if (ctident(sc, hd) < 0)
  143.         return(0);
  144.     ctreset(sc, hd);
  145.     sc->sc_dq.dq_ctlr = hd->hp_ctlr;
  146.     sc->sc_dq.dq_unit = hd->hp_unit;
  147.     sc->sc_dq.dq_slave = hd->hp_slave;
  148.     sc->sc_dq.dq_driver = &ctdriver;
  149.     sc->sc_flags |= CTF_ALIVE;
  150.     return(1);
  151. }
  152.  
  153. ctident(sc, hd)
  154.     register struct ct_softc *sc;
  155.     register struct hp_device *hd;
  156. {
  157.     struct ct_describe desc;
  158.     u_char stat, cmd[3];
  159.     char name[7];
  160.     int id, i;
  161.  
  162.     /*
  163.      * Read device id and verify that:
  164.      * 1. It is a CS80 device
  165.      * 2. It is one of our recognized tape devices
  166.      * 3. It has the proper physical unit number
  167.      */
  168.     id = hpibid(hd->hp_ctlr, hd->hp_slave);
  169.     if ((id & 0x200) == 0)
  170.         return(-1);
  171.     for (i = 0; i < nctinfo; i++)
  172.         if (id == ctinfo[i].hwid)
  173.             break;
  174.     if (i == nctinfo || sc->sc_punit != ctinfo[i].punit)
  175.         return(-1);
  176.     id = i;
  177.  
  178.     /*
  179.      * Collect device description.
  180.      * Right now we only need this to differentiate 7945 from 7946.
  181.      * Note that we always issue the describe command to unit 0.
  182.      */
  183.     cmd[0] = C_SUNIT(0);
  184.     cmd[1] = C_SVOL(0);
  185.     cmd[2] = C_DESC;
  186.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd));
  187.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37);
  188.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  189.     bzero(name, sizeof(name));
  190.     if (!stat) {
  191.         register int n = desc.d_name;
  192.         for (i = 5; i >= 0; i--) {
  193.             name[i] = (n & 0xf) + '0';
  194.             n >>= 4;
  195.         }
  196.     }
  197.     switch (ctinfo[id].hwid) {
  198.     case CT7946ID:
  199.         if (bcmp(name, "079450", 6) == 0)
  200.             return(-1);        /* not really a 7946 */
  201.         /* fall into... */
  202.     case CT9144ID:
  203.     case CT9145ID:
  204.         sc->sc_type = CT9144;
  205.         sc->sc_flags |= CTF_CANSTREAM;
  206.         break;
  207.  
  208.     case CT7912PID:
  209.     case CT7914PID:
  210.         sc->sc_type = CT88140;
  211.         break;
  212.     }
  213.     printf("ct%d: %s %stape\n", hd->hp_unit, ctinfo[id].desc,
  214.            (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " ");
  215.     return(id);
  216. }
  217.  
  218. ctreset(sc, hd)
  219.     register struct ct_softc *sc;
  220.     register struct hp_device *hd;
  221. {
  222.     u_char stat;
  223.  
  224.     sc->sc_clear.unit = C_SUNIT(sc->sc_punit);
  225.     sc->sc_clear.cmd = C_CLEAR;
  226.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear,
  227.         sizeof(sc->sc_clear));
  228.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  229.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  230.     sc->sc_src.unit = C_SUNIT(CTCTLR);
  231.     sc->sc_src.nop = C_NOP;
  232.     sc->sc_src.cmd = C_SREL;
  233.     sc->sc_src.param = C_REL;
  234.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src,
  235.         sizeof(sc->sc_src));
  236.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  237.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  238.     sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);
  239.     sc->sc_ssmc.cmd = C_SSM;
  240.     sc->sc_ssmc.refm = REF_MASK;
  241.     sc->sc_ssmc.fefm = FEF_MASK;
  242.     sc->sc_ssmc.aefm = AEF_MASK;
  243.     sc->sc_ssmc.iefm = IEF_MASK;
  244.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc,
  245.         sizeof(sc->sc_ssmc));
  246.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  247.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  248.     sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
  249.     sc->sc_soptc.nop = C_NOP;
  250.     sc->sc_soptc.cmd = C_SOPT;
  251.     sc->sc_soptc.opt = C_SPAR;
  252.     hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc,
  253.         sizeof(sc->sc_soptc));
  254.     hpibswait(hd->hp_ctlr, hd->hp_slave);
  255.     hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));
  256. }
  257.  
  258. /*ARGSUSED*/
  259. ctopen(dev, flag, type, p)
  260.     dev_t dev;
  261.     int flag, type;
  262.     struct proc *p;
  263. {
  264.     register struct ct_softc *sc = &ct_softc[UNIT(dev)];
  265.     u_char stat;
  266.     int cc;
  267.  
  268.     if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0)
  269.         return(ENXIO);
  270.     if (sc->sc_flags & CTF_OPEN)
  271.         return(EBUSY);
  272.     sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
  273.     sc->sc_soptc.nop = C_NOP;
  274.     sc->sc_soptc.cmd = C_SOPT;
  275.     if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
  276.         sc->sc_soptc.opt = C_SPAR | C_IMRPT;
  277.     else
  278.         sc->sc_soptc.opt = C_SPAR;
  279.     /* 
  280.      * Check the return of hpibsend() and hpibswait().
  281.      * Drive could be loading/unloading a tape. If not checked,
  282.      * driver hangs. 
  283.      */
  284.     cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  285.                   C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
  286.     if (cc != sizeof(sc->sc_soptc))
  287.         return(EBUSY);
  288.     hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave);
  289.     cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, 
  290.                   &stat, sizeof(stat));
  291.     if (cc != sizeof(stat))
  292.         return(EBUSY);
  293.     sc->sc_tpr = tprintf_open(p);
  294.     sc->sc_flags |= CTF_OPEN;
  295.     return(0);
  296. }
  297.  
  298. /*ARGSUSED*/
  299. ctclose(dev, flag)
  300.     dev_t dev;
  301. {
  302.     register struct ct_softc *sc = &ct_softc[UNIT(dev)];
  303.  
  304.     if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
  305.         (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
  306.         ctcommand(dev, MTWEOF, 2);
  307.         ctcommand(dev, MTBSR, 1);
  308.         if (sc->sc_eofp == EOFS - 1)
  309.             sc->sc_eofs[EOFS - 1]--;
  310.         else
  311.             sc->sc_eofp--;
  312. #ifdef DEBUG
  313.         if(ctdebug & CT_BSF)
  314.             printf("ct%d: ctclose backup eofs prt %d blk %d\n",
  315.                    UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);
  316. #endif
  317.     }
  318.     if ((minor(dev) & CT_NOREW) == 0)
  319.         ctcommand(dev, MTREW, 1);
  320.     sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
  321.     tprintf_close(sc->sc_tpr);
  322. #ifdef DEBUG
  323.     if (ctdebug & CDB_FILES)
  324.         printf("ctclose: flags %x\n", sc->sc_flags);
  325. #endif
  326.     return(0);    /* XXX */
  327. }
  328.  
  329. ctcommand(dev, cmd, cnt)
  330.     dev_t dev;
  331.     register int cnt;
  332. {
  333.     register struct ct_softc *sc = &ct_softc[UNIT(dev)];
  334.     register struct buf *bp = &ctbuf[UNIT(dev)];
  335.     register struct buf *nbp = 0;
  336.  
  337.     if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
  338.         cnt = sc->sc_eofs[EOFS - 1] - cnt;
  339.         ctcommand(dev, MTREW, 1);
  340.         ctcommand(dev, MTFSF, cnt);
  341.         cnt = 2;
  342.         cmd = MTBSR;
  343.     }
  344.  
  345.     if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
  346.         cnt = 1;
  347.         cmd = MTREW;
  348.     }
  349.  
  350.     sc->sc_flags |= CTF_CMD;
  351.     sc->sc_bp = bp;
  352.     sc->sc_cmd = cmd;
  353.     bp->b_dev = dev;
  354.     if (cmd == MTFSF) {
  355.         nbp = (struct buf *)geteblk(MAXBSIZE);
  356.         bp->b_un.b_addr = nbp->b_un.b_addr;
  357.         bp->b_bcount = MAXBSIZE;
  358.     }
  359. again:
  360.     bp->b_flags = B_BUSY;
  361.     if (cmd == MTBSF) {
  362.         sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
  363.         sc->sc_eofp--;
  364. #ifdef DEBUG
  365.         if (ctdebug & CT_BSF)
  366.             printf("ct%d: backup eof pos %d blk %d\n",
  367.                    UNIT(dev), sc->sc_eofp, 
  368.                    sc->sc_eofs[sc->sc_eofp]);
  369. #endif
  370.     }
  371.     ctstrategy(bp);
  372.     iowait(bp);
  373.     if (--cnt > 0)
  374.         goto again;
  375.     bp->b_flags = 0;
  376.     sc->sc_flags &= ~CTF_CMD;
  377.     if (nbp)
  378.         brelse(nbp);
  379. }
  380.  
  381. ctstrategy(bp)
  382.     register struct buf *bp;
  383. {
  384.     register struct buf *dp;
  385.     register int s, unit;
  386.  
  387.     unit = UNIT(bp->b_dev);
  388.     dp = &cttab[unit];
  389.     bp->av_forw = NULL;
  390.     s = splbio();
  391.     if (dp->b_actf == NULL)
  392.         dp->b_actf = bp;
  393.     else
  394.         dp->b_actl->av_forw = bp;
  395.     dp->b_actl = bp;
  396.     if (dp->b_active == 0) {
  397.         dp->b_active = 1;
  398.         ctustart(unit);
  399.     }
  400.     splx(s);
  401. }
  402.  
  403. ctustart(unit)
  404.     register int unit;
  405. {
  406.     register struct ct_softc *sc = &ct_softc[unit];
  407.     register struct buf *bp;
  408.  
  409.     bp = cttab[unit].b_actf;
  410.     sc->sc_addr = bp->b_un.b_addr;
  411.     sc->sc_resid = bp->b_bcount;
  412.     if (hpibreq(&sc->sc_dq))
  413.         ctstart(unit);
  414. }
  415.  
  416. ctstart(unit)
  417.     register int unit;
  418. {
  419.     register struct ct_softc *sc = &ct_softc[unit];
  420.     register struct buf *bp;
  421.     register int i;
  422.  
  423.     bp = cttab[unit].b_actf;
  424. again:
  425.     if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
  426.         switch(sc->sc_cmd) {
  427.  
  428.         case MTFSF:
  429.             bp->b_flags |= B_READ;
  430.             goto mustio;
  431.  
  432.         case MTBSF:
  433.             goto gotaddr;
  434.  
  435.         case MTOFFL:
  436.             sc->sc_blkno = 0;
  437.             sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
  438.             sc->sc_ul.cmd = C_UNLOAD;
  439.             hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  440.                 C_CMD, &sc->sc_ul, sizeof(sc->sc_ul));
  441.             break;
  442.  
  443.         case MTWEOF:
  444.             sc->sc_blkno++;
  445.             sc->sc_flags |= CTF_WRT;
  446.             sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
  447.             sc->sc_wfm.cmd = C_WFM;
  448.             hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  449.                 C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm));
  450.             ctaddeof(unit);
  451.             break;
  452.  
  453.         case MTBSR:
  454.             sc->sc_blkno--;
  455.             goto gotaddr;
  456.  
  457.         case MTFSR:
  458.             sc->sc_blkno++;
  459.             goto gotaddr;
  460.  
  461.         case MTREW:
  462.             sc->sc_blkno = 0;
  463. #ifdef DEBUG
  464.             if(ctdebug & CT_BSF)
  465.                 printf("ct%d: clearing eofs\n", unit);
  466. #endif
  467.             for (i=0; i<EOFS; i++)
  468.                 sc->sc_eofs[i] = 0;
  469.             sc->sc_eofp = 0;
  470.  
  471. gotaddr:
  472.             sc->sc_ioc.saddr = C_SADDR;
  473.             sc->sc_ioc.addr0 = 0;
  474.             sc->sc_ioc.addr = sc->sc_blkno;
  475.             sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
  476.             sc->sc_ioc.nop2 = C_NOP;
  477.             sc->sc_ioc.slen = C_SLEN;
  478.             sc->sc_ioc.len = 0;
  479.             sc->sc_ioc.nop3 = C_NOP;
  480.             sc->sc_ioc.cmd = C_READ;
  481.             hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  482.                 C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
  483.             break;
  484.         }
  485.     }
  486.     else {
  487. mustio:
  488.         if ((bp->b_flags & B_READ) &&
  489.             sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
  490. #ifdef DEBUG
  491.             if (ctdebug & CDB_FILES)
  492.                 printf("ctstart: before flags %x\n", sc->sc_flags);
  493. #endif
  494.             if (sc->sc_flags & CTF_BEOF) {
  495.                 sc->sc_flags &= ~CTF_BEOF;
  496.                 sc->sc_flags |= CTF_AEOF;
  497. #ifdef DEBUG
  498.                 if (ctdebug & CDB_FILES)
  499.                     printf("ctstart: after flags %x\n", sc->sc_flags);
  500. #endif
  501.             }
  502.             bp->b_resid = bp->b_bcount;
  503.             iodone(bp);
  504.             hpibfree(&sc->sc_dq);
  505.             cttab[unit].b_actf = bp = bp->av_forw;
  506.             if (bp == NULL) {
  507.                 cttab[unit].b_active = 0;
  508.                 return;
  509.             }
  510.             sc->sc_addr = bp->b_un.b_addr;
  511.             sc->sc_resid = bp->b_bcount;
  512.             if (hpibreq(&sc->sc_dq))
  513.                 goto again;
  514.             return;
  515.         }            
  516.         sc->sc_flags |= CTF_IO;
  517.         sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
  518.         sc->sc_ioc.saddr = C_SADDR;
  519.         sc->sc_ioc.addr0 = 0;
  520.         sc->sc_ioc.addr = sc->sc_blkno;
  521.         sc->sc_ioc.nop2 = C_NOP;
  522.         sc->sc_ioc.slen = C_SLEN;
  523.         sc->sc_ioc.len = sc->sc_resid;
  524.         sc->sc_ioc.nop3 = C_NOP;
  525.         if (bp->b_flags & B_READ)
  526.             sc->sc_ioc.cmd = C_READ;
  527.         else {
  528.             sc->sc_ioc.cmd = C_WRITE;
  529.             sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
  530.         }
  531.         hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
  532.             &sc->sc_ioc, sizeof(sc->sc_ioc));
  533.     }
  534.     hpibawait(sc->sc_hd->hp_ctlr);
  535. }
  536.  
  537. ctgo(unit)
  538.     register int unit;
  539. {
  540.     register struct ct_softc *sc = &ct_softc[unit];
  541.     register struct buf *bp;
  542.  
  543.     bp = cttab[unit].b_actf;
  544.     hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
  545.         sc->sc_addr, sc->sc_resid, bp->b_flags & B_READ);
  546. }
  547.  
  548. /*
  549.  * Hideous grue to handle EOF/EOT (mostly for reads)
  550.  */
  551. cteof(sc, bp)
  552.     register struct ct_softc *sc;
  553.     register struct buf *bp;
  554. {
  555.     long blks;
  556.  
  557.     /*
  558.      * EOT on a write is an error.
  559.      */
  560.     if ((bp->b_flags & B_READ) == 0) {
  561.         bp->b_resid = bp->b_bcount;
  562.         bp->b_flags |= B_ERROR;
  563.         bp->b_error = ENOSPC;
  564.         sc->sc_flags |= CTF_EOT;
  565.         return;
  566.     }
  567.     /*
  568.      * Use returned block position to determine how many blocks
  569.      * we really read and update b_resid.
  570.      */
  571.     blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
  572. #ifdef DEBUG
  573.     if (ctdebug & CDB_FILES)
  574.         printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n",
  575.                bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
  576.                blks, bp->b_bcount - CTKTOB(blks));
  577. #endif
  578.     if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
  579.         blks = 0;
  580.         sc->sc_blkno++;
  581.     }
  582.     else {
  583.         sc->sc_blkno = sc->sc_stat.c_blk;
  584.     }
  585.     bp->b_resid = bp->b_bcount - CTKTOB(blks);
  586.     /*
  587.      * If we are at physical EOV or were after an EOF,
  588.      * we are now at logical EOT.
  589.      */
  590.     if ((sc->sc_stat.c_aef & AEF_EOV) ||
  591.         (sc->sc_flags & CTF_AEOF)) {
  592.         sc->sc_flags |= CTF_EOT;
  593.         sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
  594.     }
  595.     /*
  596.      * If we were before an EOF or we have just completed a FSF,
  597.      * we are now after EOF.
  598.      */
  599.     else if ((sc->sc_flags & CTF_BEOF) ||
  600.          (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) {
  601.         sc->sc_flags |= CTF_AEOF;
  602.         sc->sc_flags &= ~CTF_BEOF;
  603.     }
  604.     /*
  605.      * Otherwise if we read something we are now before EOF
  606.      * (and no longer after EOF).
  607.      */
  608.     else if (blks) {
  609.         sc->sc_flags |= CTF_BEOF;
  610.         sc->sc_flags &= ~CTF_AEOF;
  611.     }
  612.     /*
  613.      * Finally, if we didn't read anything we just passed an EOF
  614.      */
  615.     else
  616.         sc->sc_flags |= CTF_AEOF;
  617. #ifdef DEBUG
  618.     if (ctdebug & CDB_FILES)
  619.         printf("cteof: leaving flags %x\n", sc->sc_flags);
  620. #endif
  621. }
  622.  
  623. ctintr(unit)
  624.     register int unit;
  625. {
  626.     register struct ct_softc *sc = &ct_softc[unit];
  627.     register struct buf *bp;
  628.     u_char stat;
  629.  
  630.     bp = cttab[unit].b_actf;
  631.     if (bp == NULL) {
  632.         printf("ct%d: bp == NULL\n", unit);
  633.         return;
  634.     }
  635.     if (sc->sc_flags & CTF_IO) {
  636.         sc->sc_flags &= ~CTF_IO;
  637.         if (hpibustart(sc->sc_hd->hp_ctlr))
  638.             ctgo(unit);
  639.         return;
  640.     }
  641.     if ((sc->sc_flags & CTF_STATWAIT) == 0) {
  642.         if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) {
  643.             sc->sc_flags |= CTF_STATWAIT;
  644.             hpibawait(sc->sc_hd->hp_ctlr);
  645.             return;
  646.         }
  647.     } else
  648.         sc->sc_flags &= ~CTF_STATWAIT;
  649.     hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1);
  650. #ifdef DEBUG
  651.     if (ctdebug & CDB_FILES)
  652.         printf("ctintr: before flags %x\n", sc->sc_flags);
  653. #endif
  654.     if (stat) {
  655.         sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
  656.         sc->sc_rsc.cmd = C_STATUS;
  657.         hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
  658.             &sc->sc_rsc, sizeof(sc->sc_rsc));
  659.         hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
  660.             &sc->sc_stat, sizeof(sc->sc_stat));
  661.         hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
  662.             &stat, 1);
  663. #ifdef DEBUG
  664.         if (ctdebug & CDB_FILES)
  665.             printf("ctintr: return stat 0x%x, A%x F%x blk %d\n",
  666.                    stat, sc->sc_stat.c_aef,
  667.                    sc->sc_stat.c_fef, sc->sc_stat.c_blk);
  668. #endif
  669.         if (stat == 0) {
  670.             if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
  671.                 cteof(sc, bp);
  672.                 ctaddeof(unit);
  673.                 goto done;
  674.             }
  675.             if (sc->sc_stat.c_fef & FEF_PF) {
  676.                 ctreset(sc, sc->sc_hd);
  677.                 ctstart(unit);
  678.                 return;
  679.             }
  680.             if (sc->sc_stat.c_fef & FEF_REXMT) {
  681.                 ctstart(unit);
  682.                 return;
  683.             }
  684.             if (sc->sc_stat.c_aef & 0x5800) {
  685.                 if (sc->sc_stat.c_aef & 0x4000)
  686.                     tprintf(sc->sc_tpr,
  687.                         "ct%d: uninitialized media\n",
  688.                         unit);
  689.                 if (sc->sc_stat.c_aef & 0x1000)
  690.                     tprintf(sc->sc_tpr,
  691.                         "ct%d: not ready\n", unit);
  692.                 if (sc->sc_stat.c_aef & 0x0800)
  693.                     tprintf(sc->sc_tpr,
  694.                         "ct%d: write protect\n", unit);
  695.             } else {
  696.                 printf("ct%d err: v%d u%d ru%d bn%d, ",
  697.                        unit,
  698.                        (sc->sc_stat.c_vu>>4)&0xF,
  699.                        sc->sc_stat.c_vu&0xF,
  700.                        sc->sc_stat.c_pend,
  701.                        sc->sc_stat.c_blk);
  702.                 printf("R0x%x F0x%x A0x%x I0x%x\n",
  703.                        sc->sc_stat.c_ref,
  704.                        sc->sc_stat.c_fef,
  705.                        sc->sc_stat.c_aef,
  706.                        sc->sc_stat.c_ief);
  707.             }
  708.         } else
  709.             printf("ct%d: request status failed\n", unit);
  710.         bp->b_flags |= B_ERROR;
  711.         bp->b_error = EIO;
  712.         goto done;
  713.     } else
  714.         bp->b_resid = 0;
  715.     if (sc->sc_flags & CTF_CMD) {
  716.         switch (sc->sc_cmd) {
  717.         case MTFSF:
  718.             sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
  719.             sc->sc_blkno += CTBTOK(sc->sc_resid);
  720.             ctstart(unit);
  721.             return;
  722.         case MTBSF:
  723.             sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
  724.             break;
  725.         case MTBSR:
  726.             sc->sc_flags &= ~CTF_BEOF;
  727.             if (sc->sc_flags & CTF_EOT) {
  728.                 sc->sc_flags |= CTF_AEOF;
  729.                 sc->sc_flags &= ~CTF_EOT;
  730.             } else if (sc->sc_flags & CTF_AEOF) {
  731.                 sc->sc_flags |= CTF_BEOF;
  732.                 sc->sc_flags &= ~CTF_AEOF;
  733.             }
  734.             break;
  735.         case MTWEOF:
  736.             sc->sc_flags &= ~CTF_BEOF;
  737.             if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
  738.                 sc->sc_flags |= CTF_EOT;
  739.                 sc->sc_flags &= ~CTF_AEOF;
  740.             } else
  741.                 sc->sc_flags |= CTF_AEOF;
  742.             break;
  743.         case MTREW:
  744.         case MTOFFL:
  745.             sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
  746.             break;
  747.         }
  748.     } else {
  749.         sc->sc_flags &= ~CTF_AEOF;
  750.         sc->sc_blkno += CTBTOK(sc->sc_resid);
  751.     }
  752. done:
  753. #ifdef DEBUG
  754.     if (ctdebug & CDB_FILES)
  755.         printf("ctintr: after flags %x\n", sc->sc_flags);
  756. #endif
  757.     cttab[unit].b_actf = bp->av_forw;
  758.     iodone(bp);
  759.     hpibfree(&sc->sc_dq);
  760.     if (cttab[unit].b_actf == NULL) {
  761.         cttab[unit].b_active = 0;
  762.         return;
  763.     }
  764.     ctustart(unit);
  765. }
  766.  
  767. ctread(dev, uio)
  768.     dev_t dev;
  769.     struct uio *uio;
  770. {
  771.     register int unit = UNIT(dev);
  772.  
  773.     return(physio(ctstrategy, &ctbuf[unit], dev, B_READ, minphys, uio));
  774. }
  775.  
  776. ctwrite(dev, uio)
  777.     dev_t dev;
  778.     struct uio *uio;
  779. {
  780.     register int unit = UNIT(dev);
  781.  
  782.     return(physio(ctstrategy, &ctbuf[unit], dev, B_WRITE, minphys, uio));
  783. }
  784.  
  785. /*ARGSUSED*/
  786. ctioctl(dev, cmd, data, flag)
  787.     dev_t dev;
  788.     caddr_t data;
  789. {
  790.     register struct mtop *op;
  791.     register int cnt;
  792.  
  793.     switch (cmd) {
  794.  
  795.     case MTIOCTOP:
  796.         op = (struct mtop *)data;
  797.         switch(op->mt_op) {
  798.  
  799.         case MTWEOF:
  800.         case MTFSF:
  801.         case MTBSR:
  802.         case MTBSF:
  803.         case MTFSR:
  804.             cnt = op->mt_count;
  805.             break;
  806.  
  807.         case MTREW:
  808.         case MTOFFL:
  809.             cnt = 1;
  810.             break;
  811.  
  812.         default:
  813.             return(EINVAL);
  814.         }
  815.         ctcommand(dev, op->mt_op, cnt);
  816.         break;
  817.  
  818.     case MTIOCGET:
  819.         break;
  820.  
  821.     default:
  822.         return(EINVAL);
  823.     }
  824.     return(0);
  825. }
  826.  
  827. /*ARGSUSED*/
  828. ctdump(dev)
  829.     dev_t dev;
  830. {
  831.     return(ENXIO);
  832. }
  833.  
  834. ctaddeof(unit)
  835.     int unit;
  836. {
  837.     register struct ct_softc *sc = &ct_softc[unit];
  838.     
  839.     if (sc->sc_eofp == EOFS - 1)
  840.         sc->sc_eofs[EOFS - 1]++;
  841.     else {
  842.         sc->sc_eofp++;
  843.         if (sc->sc_eofp == EOFS - 1)
  844.             sc->sc_eofs[EOFS - 1] = EOFS;
  845.         else
  846.             /* save blkno */
  847.             sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
  848.     }
  849. #ifdef DEBUG
  850.     if (ctdebug & CT_BSF)
  851.         printf("ct%d: add eof pos %d blk %d\n",
  852.                unit, sc->sc_eofp,
  853.                sc->sc_eofs[sc->sc_eofp]);
  854. #endif
  855. }
  856. #endif
  857.