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