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