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