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