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