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