📄 ct.c
字号:
/* * Copyright (c) 1982, 1990, 1993 * The Regents of the University of California. All rights reserved. * * 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. * * 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. * * @(#)ct.c 8.2 (Berkeley) 1/12/94 */#include "ct.h"#if NCT > 0/* * CS80 cartridge tape driver (9144, 88140, 9145) * * Reminder: * C_CC bit (character count option) when used in the CS/80 command * 'set options' will cause the tape not to stream. * * TODO: * make filesystem compatible * make block mode work according to mtio(4) spec. (if possible) * merge with cs80 disk driver * finish support of 9145 */#include <sys/param.h>#include <sys/buf.h>#include <sys/ioctl.h>#include <sys/mtio.h>#include <sys/tprintf.h>#include <sys/proc.h>#include <hp/dev/device.h>#include <hp300/dev/ctreg.h>/* number of eof marks to remember */#define EOFS 128int ctinit(), ctstart(), ctgo(), ctintr();struct driver ctdriver = { ctinit, "ct", ctstart, ctgo, ctintr,};struct ct_softc { struct hp_device *sc_hd; struct ct_iocmd sc_ioc; struct ct_rscmd sc_rsc; struct ct_stat sc_stat; struct ct_ssmcmd sc_ssmc; struct ct_srcmd sc_src; struct ct_soptcmd sc_soptc; struct ct_ulcmd sc_ul; struct ct_wfmcmd sc_wfm; struct ct_clearcmd sc_clear; struct buf *sc_bp; int sc_blkno; int sc_cmd; int sc_resid; char *sc_addr; int sc_flags; short sc_type; short sc_punit; tpr_t sc_tpr; struct devqueue sc_dq; int sc_eofp; int sc_eofs[EOFS];} ct_softc[NCT];/* flags */#define CTF_OPEN 0x01#define CTF_ALIVE 0x02#define CTF_WRT 0x04#define CTF_CMD 0x08#define CTF_IO 0x10#define CTF_BEOF 0x20#define CTF_AEOF 0x40#define CTF_EOT 0x80#define CTF_STATWAIT 0x100#define CTF_CANSTREAM 0x200#define CTF_WRTTN 0x400struct ctinfo { short hwid; short punit; char *desc;} ctinfo[] = { CT7946ID, 1, "7946A", CT7912PID, 1, "7912P", CT7914PID, 1, "7914P", CT9144ID, 0, "9144", CT9145ID, 0, "9145",};int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);struct buf cttab[NCT];struct buf ctbuf[NCT];#define CT_NOREW 4#define CT_STREAM 8#define UNIT(x) (minor(x) & 3)#define ctpunit(x) ((x) & 7)#ifdef DEBUGint ctdebug = 0;#define CDB_FILES 0x01#define CT_BSF 0x02#endifctinit(hd) register struct hp_device *hd;{ register struct ct_softc *sc = &ct_softc[hd->hp_unit]; register struct buf *bp; for (bp = cttab; bp < &cttab[NCT]; bp++) bp->b_actb = &bp->b_actf; sc->sc_hd = hd; sc->sc_punit = ctpunit(hd->hp_flags); if (ctident(sc, hd) < 0) return(0); ctreset(sc, hd); sc->sc_dq.dq_ctlr = hd->hp_ctlr; sc->sc_dq.dq_unit = hd->hp_unit; sc->sc_dq.dq_slave = hd->hp_slave; sc->sc_dq.dq_driver = &ctdriver; sc->sc_flags |= CTF_ALIVE; return(1);}ctident(sc, hd) register struct ct_softc *sc; register struct hp_device *hd;{ struct ct_describe desc; u_char stat, cmd[3]; char name[7]; int id, i; /* * Read device id and verify that: * 1. It is a CS80 device * 2. It is one of our recognized tape devices * 3. It has the proper physical unit number */ id = hpibid(hd->hp_ctlr, hd->hp_slave); if ((id & 0x200) == 0) return(-1); for (i = 0; i < nctinfo; i++) if (id == ctinfo[i].hwid) break; if (i == nctinfo || sc->sc_punit != ctinfo[i].punit) return(-1); id = i; /* * Collect device description. * Right now we only need this to differentiate 7945 from 7946. * Note that we always issue the describe command to unit 0. */ cmd[0] = C_SUNIT(0); cmd[1] = C_SVOL(0); cmd[2] = C_DESC; hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd)); hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37); hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); bzero(name, sizeof(name)); if (!stat) { register int n = desc.d_name; for (i = 5; i >= 0; i--) { name[i] = (n & 0xf) + '0'; n >>= 4; } } switch (ctinfo[id].hwid) { case CT7946ID: if (bcmp(name, "079450", 6) == 0) return(-1); /* not really a 7946 */ /* fall into... */ case CT9144ID: case CT9145ID: sc->sc_type = CT9144; sc->sc_flags |= CTF_CANSTREAM; break; case CT7912PID: case CT7914PID: sc->sc_type = CT88140; break; } printf("ct%d: %s %stape\n", hd->hp_unit, ctinfo[id].desc, (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " "); return(id);}ctreset(sc, hd) register struct ct_softc *sc; register struct hp_device *hd;{ u_char stat; sc->sc_clear.unit = C_SUNIT(sc->sc_punit); sc->sc_clear.cmd = C_CLEAR; hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear)); hpibswait(hd->hp_ctlr, hd->hp_slave); hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); sc->sc_src.unit = C_SUNIT(CTCTLR); sc->sc_src.nop = C_NOP; sc->sc_src.cmd = C_SREL; sc->sc_src.param = C_REL; hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src)); hpibswait(hd->hp_ctlr, hd->hp_slave); hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit); sc->sc_ssmc.cmd = C_SSM; sc->sc_ssmc.refm = REF_MASK; sc->sc_ssmc.fefm = FEF_MASK; sc->sc_ssmc.aefm = AEF_MASK; sc->sc_ssmc.iefm = IEF_MASK; hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc)); hpibswait(hd->hp_ctlr, hd->hp_slave); hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); sc->sc_soptc.unit = C_SUNIT(sc->sc_punit); sc->sc_soptc.nop = C_NOP; sc->sc_soptc.cmd = C_SOPT; sc->sc_soptc.opt = C_SPAR; hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc)); hpibswait(hd->hp_ctlr, hd->hp_slave); hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));}/*ARGSUSED*/ctopen(dev, flag, type, p) dev_t dev; int flag, type; struct proc *p;{ register struct ct_softc *sc = &ct_softc[UNIT(dev)]; u_char stat; int cc; if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0) return(ENXIO); if (sc->sc_flags & CTF_OPEN) return(EBUSY); sc->sc_soptc.unit = C_SUNIT(sc->sc_punit); sc->sc_soptc.nop = C_NOP; sc->sc_soptc.cmd = C_SOPT; if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM)) sc->sc_soptc.opt = C_SPAR | C_IMRPT; else sc->sc_soptc.opt = C_SPAR; /* * Check the return of hpibsend() and hpibswait(). * Drive could be loading/unloading a tape. If not checked, * driver hangs. */ cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc)); if (cc != sizeof(sc->sc_soptc)) return(EBUSY); hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave); cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); if (cc != sizeof(stat)) return(EBUSY); sc->sc_tpr = tprintf_open(p); sc->sc_flags |= CTF_OPEN; return(0);}/*ARGSUSED*/ctclose(dev, flag) dev_t dev; int flag;{ register struct ct_softc *sc = &ct_softc[UNIT(dev)]; if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ ctcommand(dev, MTWEOF, 2); ctcommand(dev, MTBSR, 1); if (sc->sc_eofp == EOFS - 1) sc->sc_eofs[EOFS - 1]--; else sc->sc_eofp--;#ifdef DEBUG if(ctdebug & CT_BSF) printf("ct%d: ctclose backup eofs prt %d blk %d\n", UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);#endif } if ((minor(dev) & CT_NOREW) == 0) ctcommand(dev, MTREW, 1); sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); tprintf_close(sc->sc_tpr);#ifdef DEBUG if (ctdebug & CDB_FILES) printf("ctclose: flags %x\n", sc->sc_flags);#endif return(0); /* XXX */}ctcommand(dev, cmd, cnt) dev_t dev; int cmd; register int cnt;{ register struct ct_softc *sc = &ct_softc[UNIT(dev)]; register struct buf *bp = &ctbuf[UNIT(dev)]; register struct buf *nbp = 0; if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { cnt = sc->sc_eofs[EOFS - 1] - cnt; ctcommand(dev, MTREW, 1); ctcommand(dev, MTFSF, cnt); cnt = 2; cmd = MTBSR; } if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { cnt = 1; cmd = MTREW; } sc->sc_flags |= CTF_CMD; sc->sc_bp = bp; sc->sc_cmd = cmd; bp->b_dev = dev; if (cmd == MTFSF) { nbp = (struct buf *)geteblk(MAXBSIZE); bp->b_un.b_addr = nbp->b_un.b_addr; bp->b_bcount = MAXBSIZE; }again: bp->b_flags = B_BUSY; if (cmd == MTBSF) { sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; sc->sc_eofp--;#ifdef DEBUG if (ctdebug & CT_BSF) printf("ct%d: backup eof pos %d blk %d\n", UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);#endif } ctstrategy(bp); iowait(bp); if (--cnt > 0) goto again; bp->b_flags = 0; sc->sc_flags &= ~CTF_CMD; if (nbp) brelse(nbp);}ctstrategy(bp) register struct buf *bp;{ register struct buf *dp; register int s, unit; unit = UNIT(bp->b_dev); dp = &cttab[unit]; bp->b_actf = NULL; s = splbio(); 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; ctustart(unit); } splx(s);}ctustart(unit) register int unit;{ register struct ct_softc *sc = &ct_softc[unit]; register struct buf *bp; bp = cttab[unit].b_actf; sc->sc_addr = bp->b_un.b_addr; sc->sc_resid = bp->b_bcount; if (hpibreq(&sc->sc_dq)) ctstart(unit);}ctstart(unit) register int unit;{ register struct ct_softc *sc = &ct_softc[unit]; register struct buf *bp, *dp; register int i; bp = cttab[unit].b_actf;again: if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { switch(sc->sc_cmd) { case MTFSF: bp->b_flags |= B_READ; goto mustio;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -