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