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