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