xref: /original-bsd/sys/hp300/dev/ct.c (revision 3705696b)
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.1 (Berkeley) 06/10/93
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 {
280 	register struct ct_softc *sc = &ct_softc[UNIT(dev)];
281 
282 	if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
283 	    (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
284 		ctcommand(dev, MTWEOF, 2);
285 		ctcommand(dev, MTBSR, 1);
286 		if (sc->sc_eofp == EOFS - 1)
287 			sc->sc_eofs[EOFS - 1]--;
288 		else
289 			sc->sc_eofp--;
290 #ifdef DEBUG
291 		if(ctdebug & CT_BSF)
292 			printf("ct%d: ctclose backup eofs prt %d blk %d\n",
293 			       UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]);
294 #endif
295 	}
296 	if ((minor(dev) & CT_NOREW) == 0)
297 		ctcommand(dev, MTREW, 1);
298 	sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
299 	tprintf_close(sc->sc_tpr);
300 #ifdef DEBUG
301 	if (ctdebug & CDB_FILES)
302 		printf("ctclose: flags %x\n", sc->sc_flags);
303 #endif
304 	return(0);	/* XXX */
305 }
306 
307 ctcommand(dev, cmd, cnt)
308 	dev_t dev;
309 	register int cnt;
310 {
311 	register struct ct_softc *sc = &ct_softc[UNIT(dev)];
312 	register struct buf *bp = &ctbuf[UNIT(dev)];
313 	register struct buf *nbp = 0;
314 
315 	if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
316 		cnt = sc->sc_eofs[EOFS - 1] - cnt;
317 		ctcommand(dev, MTREW, 1);
318 		ctcommand(dev, MTFSF, cnt);
319 		cnt = 2;
320 		cmd = MTBSR;
321 	}
322 
323 	if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
324 		cnt = 1;
325 		cmd = MTREW;
326 	}
327 
328 	sc->sc_flags |= CTF_CMD;
329 	sc->sc_bp = bp;
330 	sc->sc_cmd = cmd;
331 	bp->b_dev = dev;
332 	if (cmd == MTFSF) {
333 		nbp = (struct buf *)geteblk(MAXBSIZE);
334 		bp->b_un.b_addr = nbp->b_un.b_addr;
335 		bp->b_bcount = MAXBSIZE;
336 	}
337 again:
338 	bp->b_flags = B_BUSY;
339 	if (cmd == MTBSF) {
340 		sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
341 		sc->sc_eofp--;
342 #ifdef DEBUG
343 		if (ctdebug & CT_BSF)
344 			printf("ct%d: backup eof pos %d blk %d\n",
345 			       UNIT(dev), sc->sc_eofp,
346 			       sc->sc_eofs[sc->sc_eofp]);
347 #endif
348 	}
349 	ctstrategy(bp);
350 	iowait(bp);
351 	if (--cnt > 0)
352 		goto again;
353 	bp->b_flags = 0;
354 	sc->sc_flags &= ~CTF_CMD;
355 	if (nbp)
356 		brelse(nbp);
357 }
358 
359 ctstrategy(bp)
360 	register struct buf *bp;
361 {
362 	register struct buf *dp;
363 	register int s, unit;
364 
365 	unit = UNIT(bp->b_dev);
366 	dp = &cttab[unit];
367 	bp->b_actf = NULL;
368 	s = splbio();
369 	bp->b_actb = dp->b_actb;
370 	*dp->b_actb = bp;
371 	dp->b_actb = &bp->b_actf;
372 	if (dp->b_active == 0) {
373 		dp->b_active = 1;
374 		ctustart(unit);
375 	}
376 	splx(s);
377 }
378 
379 ctustart(unit)
380 	register int unit;
381 {
382 	register struct ct_softc *sc = &ct_softc[unit];
383 	register struct buf *bp;
384 
385 	bp = cttab[unit].b_actf;
386 	sc->sc_addr = bp->b_un.b_addr;
387 	sc->sc_resid = bp->b_bcount;
388 	if (hpibreq(&sc->sc_dq))
389 		ctstart(unit);
390 }
391 
392 ctstart(unit)
393 	register int unit;
394 {
395 	register struct ct_softc *sc = &ct_softc[unit];
396 	register struct buf *bp, *dp;
397 	register int i;
398 
399 	bp = cttab[unit].b_actf;
400 again:
401 	if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
402 		switch(sc->sc_cmd) {
403 
404 		case MTFSF:
405 			bp->b_flags |= B_READ;
406 			goto mustio;
407 
408 		case MTBSF:
409 			goto gotaddr;
410 
411 		case MTOFFL:
412 			sc->sc_blkno = 0;
413 			sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
414 			sc->sc_ul.cmd = C_UNLOAD;
415 			hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
416 				C_CMD, &sc->sc_ul, sizeof(sc->sc_ul));
417 			break;
418 
419 		case MTWEOF:
420 			sc->sc_blkno++;
421 			sc->sc_flags |= CTF_WRT;
422 			sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
423 			sc->sc_wfm.cmd = C_WFM;
424 			hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
425 				C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm));
426 			ctaddeof(unit);
427 			break;
428 
429 		case MTBSR:
430 			sc->sc_blkno--;
431 			goto gotaddr;
432 
433 		case MTFSR:
434 			sc->sc_blkno++;
435 			goto gotaddr;
436 
437 		case MTREW:
438 			sc->sc_blkno = 0;
439 #ifdef DEBUG
440 			if(ctdebug & CT_BSF)
441 				printf("ct%d: clearing eofs\n", unit);
442 #endif
443 			for (i=0; i<EOFS; i++)
444 				sc->sc_eofs[i] = 0;
445 			sc->sc_eofp = 0;
446 
447 gotaddr:
448 			sc->sc_ioc.saddr = C_SADDR;
449 			sc->sc_ioc.addr0 = 0;
450 			sc->sc_ioc.addr = sc->sc_blkno;
451 			sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
452 			sc->sc_ioc.nop2 = C_NOP;
453 			sc->sc_ioc.slen = C_SLEN;
454 			sc->sc_ioc.len = 0;
455 			sc->sc_ioc.nop3 = C_NOP;
456 			sc->sc_ioc.cmd = C_READ;
457 			hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
458 				C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
459 			break;
460 		}
461 	}
462 	else {
463 mustio:
464 		if ((bp->b_flags & B_READ) &&
465 		    sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
466 #ifdef DEBUG
467 			if (ctdebug & CDB_FILES)
468 				printf("ctstart: before flags %x\n", sc->sc_flags);
469 #endif
470 			if (sc->sc_flags & CTF_BEOF) {
471 				sc->sc_flags &= ~CTF_BEOF;
472 				sc->sc_flags |= CTF_AEOF;
473 #ifdef DEBUG
474 				if (ctdebug & CDB_FILES)
475 					printf("ctstart: after flags %x\n", sc->sc_flags);
476 #endif
477 			}
478 			bp->b_resid = bp->b_bcount;
479 			iodone(bp);
480 			hpibfree(&sc->sc_dq);
481 			if (dp = bp->b_actf)
482 				dp->b_actb = bp->b_actb;
483 			else
484 				cttab[unit].b_actb = bp->b_actb;
485 			*bp->b_actb = dp;
486 			if ((bp = dp) == NULL) {
487 				cttab[unit].b_active = 0;
488 				return;
489 			}
490 			sc->sc_addr = bp->b_un.b_addr;
491 			sc->sc_resid = bp->b_bcount;
492 			if (hpibreq(&sc->sc_dq))
493 				goto again;
494 			return;
495 		}
496 		sc->sc_flags |= CTF_IO;
497 		sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
498 		sc->sc_ioc.saddr = C_SADDR;
499 		sc->sc_ioc.addr0 = 0;
500 		sc->sc_ioc.addr = sc->sc_blkno;
501 		sc->sc_ioc.nop2 = C_NOP;
502 		sc->sc_ioc.slen = C_SLEN;
503 		sc->sc_ioc.len = sc->sc_resid;
504 		sc->sc_ioc.nop3 = C_NOP;
505 		if (bp->b_flags & B_READ)
506 			sc->sc_ioc.cmd = C_READ;
507 		else {
508 			sc->sc_ioc.cmd = C_WRITE;
509 			sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
510 		}
511 		hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
512 			&sc->sc_ioc, sizeof(sc->sc_ioc));
513 	}
514 	hpibawait(sc->sc_hd->hp_ctlr);
515 }
516 
517 ctgo(unit)
518 	register int unit;
519 {
520 	register struct ct_softc *sc = &ct_softc[unit];
521 	register struct buf *bp;
522 
523 	bp = cttab[unit].b_actf;
524 	hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
525 		sc->sc_addr, sc->sc_resid, bp->b_flags & B_READ);
526 }
527 
528 /*
529  * Hideous grue to handle EOF/EOT (mostly for reads)
530  */
531 cteof(sc, bp)
532 	register struct ct_softc *sc;
533 	register struct buf *bp;
534 {
535 	long blks;
536 
537 	/*
538 	 * EOT on a write is an error.
539 	 */
540 	if ((bp->b_flags & B_READ) == 0) {
541 		bp->b_resid = bp->b_bcount;
542 		bp->b_flags |= B_ERROR;
543 		bp->b_error = ENOSPC;
544 		sc->sc_flags |= CTF_EOT;
545 		return;
546 	}
547 	/*
548 	 * Use returned block position to determine how many blocks
549 	 * we really read and update b_resid.
550 	 */
551 	blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
552 #ifdef DEBUG
553 	if (ctdebug & CDB_FILES)
554 		printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n",
555 		       bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
556 		       blks, bp->b_bcount - CTKTOB(blks));
557 #endif
558 	if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
559 		blks = 0;
560 		sc->sc_blkno++;
561 	}
562 	else {
563 		sc->sc_blkno = sc->sc_stat.c_blk;
564 	}
565 	bp->b_resid = bp->b_bcount - CTKTOB(blks);
566 	/*
567 	 * If we are at physical EOV or were after an EOF,
568 	 * we are now at logical EOT.
569 	 */
570 	if ((sc->sc_stat.c_aef & AEF_EOV) ||
571 	    (sc->sc_flags & CTF_AEOF)) {
572 		sc->sc_flags |= CTF_EOT;
573 		sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
574 	}
575 	/*
576 	 * If we were before an EOF or we have just completed a FSF,
577 	 * we are now after EOF.
578 	 */
579 	else if ((sc->sc_flags & CTF_BEOF) ||
580 		 (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) {
581 		sc->sc_flags |= CTF_AEOF;
582 		sc->sc_flags &= ~CTF_BEOF;
583 	}
584 	/*
585 	 * Otherwise if we read something we are now before EOF
586 	 * (and no longer after EOF).
587 	 */
588 	else if (blks) {
589 		sc->sc_flags |= CTF_BEOF;
590 		sc->sc_flags &= ~CTF_AEOF;
591 	}
592 	/*
593 	 * Finally, if we didn't read anything we just passed an EOF
594 	 */
595 	else
596 		sc->sc_flags |= CTF_AEOF;
597 #ifdef DEBUG
598 	if (ctdebug & CDB_FILES)
599 		printf("cteof: leaving flags %x\n", sc->sc_flags);
600 #endif
601 }
602 
603 ctintr(unit)
604 	register int unit;
605 {
606 	register struct ct_softc *sc = &ct_softc[unit];
607 	register struct buf *bp, *dp;
608 	u_char stat;
609 
610 	bp = cttab[unit].b_actf;
611 	if (bp == NULL) {
612 		printf("ct%d: bp == NULL\n", unit);
613 		return;
614 	}
615 	if (sc->sc_flags & CTF_IO) {
616 		sc->sc_flags &= ~CTF_IO;
617 		if (hpibustart(sc->sc_hd->hp_ctlr))
618 			ctgo(unit);
619 		return;
620 	}
621 	if ((sc->sc_flags & CTF_STATWAIT) == 0) {
622 		if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) {
623 			sc->sc_flags |= CTF_STATWAIT;
624 			hpibawait(sc->sc_hd->hp_ctlr);
625 			return;
626 		}
627 	} else
628 		sc->sc_flags &= ~CTF_STATWAIT;
629 	hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1);
630 #ifdef DEBUG
631 	if (ctdebug & CDB_FILES)
632 		printf("ctintr: before flags %x\n", sc->sc_flags);
633 #endif
634 	if (stat) {
635 		sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
636 		sc->sc_rsc.cmd = C_STATUS;
637 		hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD,
638 			&sc->sc_rsc, sizeof(sc->sc_rsc));
639 		hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC,
640 			&sc->sc_stat, sizeof(sc->sc_stat));
641 		hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT,
642 			&stat, 1);
643 #ifdef DEBUG
644 		if (ctdebug & CDB_FILES)
645 			printf("ctintr: return stat 0x%x, A%x F%x blk %d\n",
646 			       stat, sc->sc_stat.c_aef,
647 			       sc->sc_stat.c_fef, sc->sc_stat.c_blk);
648 #endif
649 		if (stat == 0) {
650 			if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
651 				cteof(sc, bp);
652 				ctaddeof(unit);
653 				goto done;
654 			}
655 			if (sc->sc_stat.c_fef & FEF_PF) {
656 				ctreset(sc, sc->sc_hd);
657 				ctstart(unit);
658 				return;
659 			}
660 			if (sc->sc_stat.c_fef & FEF_REXMT) {
661 				ctstart(unit);
662 				return;
663 			}
664 			if (sc->sc_stat.c_aef & 0x5800) {
665 				if (sc->sc_stat.c_aef & 0x4000)
666 					tprintf(sc->sc_tpr,
667 						"ct%d: uninitialized media\n",
668 						unit);
669 				if (sc->sc_stat.c_aef & 0x1000)
670 					tprintf(sc->sc_tpr,
671 						"ct%d: not ready\n", unit);
672 				if (sc->sc_stat.c_aef & 0x0800)
673 					tprintf(sc->sc_tpr,
674 						"ct%d: write protect\n", unit);
675 			} else {
676 				printf("ct%d err: v%d u%d ru%d bn%d, ",
677 				       unit,
678 				       (sc->sc_stat.c_vu>>4)&0xF,
679 				       sc->sc_stat.c_vu&0xF,
680 				       sc->sc_stat.c_pend,
681 				       sc->sc_stat.c_blk);
682 				printf("R0x%x F0x%x A0x%x I0x%x\n",
683 				       sc->sc_stat.c_ref,
684 				       sc->sc_stat.c_fef,
685 				       sc->sc_stat.c_aef,
686 				       sc->sc_stat.c_ief);
687 			}
688 		} else
689 			printf("ct%d: request status failed\n", unit);
690 		bp->b_flags |= B_ERROR;
691 		bp->b_error = EIO;
692 		goto done;
693 	} else
694 		bp->b_resid = 0;
695 	if (sc->sc_flags & CTF_CMD) {
696 		switch (sc->sc_cmd) {
697 		case MTFSF:
698 			sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
699 			sc->sc_blkno += CTBTOK(sc->sc_resid);
700 			ctstart(unit);
701 			return;
702 		case MTBSF:
703 			sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
704 			break;
705 		case MTBSR:
706 			sc->sc_flags &= ~CTF_BEOF;
707 			if (sc->sc_flags & CTF_EOT) {
708 				sc->sc_flags |= CTF_AEOF;
709 				sc->sc_flags &= ~CTF_EOT;
710 			} else if (sc->sc_flags & CTF_AEOF) {
711 				sc->sc_flags |= CTF_BEOF;
712 				sc->sc_flags &= ~CTF_AEOF;
713 			}
714 			break;
715 		case MTWEOF:
716 			sc->sc_flags &= ~CTF_BEOF;
717 			if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
718 				sc->sc_flags |= CTF_EOT;
719 				sc->sc_flags &= ~CTF_AEOF;
720 			} else
721 				sc->sc_flags |= CTF_AEOF;
722 			break;
723 		case MTREW:
724 		case MTOFFL:
725 			sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
726 			break;
727 		}
728 	} else {
729 		sc->sc_flags &= ~CTF_AEOF;
730 		sc->sc_blkno += CTBTOK(sc->sc_resid);
731 	}
732 done:
733 #ifdef DEBUG
734 	if (ctdebug & CDB_FILES)
735 		printf("ctintr: after flags %x\n", sc->sc_flags);
736 #endif
737 	if (dp = bp->b_actf)
738 		dp->b_actb = bp->b_actb;
739 	else
740 		cttab[unit].b_actb = bp->b_actb;
741 	*bp->b_actb = dp;
742 	iodone(bp);
743 	hpibfree(&sc->sc_dq);
744 	if (cttab[unit].b_actf == NULL) {
745 		cttab[unit].b_active = 0;
746 		return;
747 	}
748 	ctustart(unit);
749 }
750 
751 ctread(dev, uio)
752 	dev_t dev;
753 	struct uio *uio;
754 {
755 	register int unit = UNIT(dev);
756 
757 	return(physio(ctstrategy, &ctbuf[unit], dev, B_READ, minphys, uio));
758 }
759 
760 ctwrite(dev, uio)
761 	dev_t dev;
762 	struct uio *uio;
763 {
764 	register int unit = UNIT(dev);
765 
766 	return(physio(ctstrategy, &ctbuf[unit], dev, B_WRITE, minphys, uio));
767 }
768 
769 /*ARGSUSED*/
770 ctioctl(dev, cmd, data, flag)
771 	dev_t dev;
772 	caddr_t data;
773 {
774 	register struct mtop *op;
775 	register int cnt;
776 
777 	switch (cmd) {
778 
779 	case MTIOCTOP:
780 		op = (struct mtop *)data;
781 		switch(op->mt_op) {
782 
783 		case MTWEOF:
784 		case MTFSF:
785 		case MTBSR:
786 		case MTBSF:
787 		case MTFSR:
788 			cnt = op->mt_count;
789 			break;
790 
791 		case MTREW:
792 		case MTOFFL:
793 			cnt = 1;
794 			break;
795 
796 		default:
797 			return(EINVAL);
798 		}
799 		ctcommand(dev, op->mt_op, cnt);
800 		break;
801 
802 	case MTIOCGET:
803 		break;
804 
805 	default:
806 		return(EINVAL);
807 	}
808 	return(0);
809 }
810 
811 /*ARGSUSED*/
812 ctdump(dev)
813 	dev_t dev;
814 {
815 	return(ENXIO);
816 }
817 
818 ctaddeof(unit)
819 	int unit;
820 {
821 	register struct ct_softc *sc = &ct_softc[unit];
822 
823 	if (sc->sc_eofp == EOFS - 1)
824 		sc->sc_eofs[EOFS - 1]++;
825 	else {
826 		sc->sc_eofp++;
827 		if (sc->sc_eofp == EOFS - 1)
828 			sc->sc_eofs[EOFS - 1] = EOFS;
829 		else
830 			/* save blkno */
831 			sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
832 	}
833 #ifdef DEBUG
834 	if (ctdebug & CT_BSF)
835 		printf("ct%d: add eof pos %d blk %d\n",
836 		       unit, sc->sc_eofp,
837 		       sc->sc_eofs[sc->sc_eofp]);
838 #endif
839 }
840 #endif
841