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