xref: /netbsd-src/sys/dev/qbus/ts.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: ts.c,v 1.33 2019/12/08 19:52:37 ad Exp $ */
2 
3 /*-
4  * Copyright (c) 1991 The Regents of the University of California.
5  * 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. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)tmscp.c	7.16 (Berkeley) 5/9/91
32  */
33 
34 /*
35  * sccsid = "@(#)tmscp.c	1.24	(ULTRIX)	1/21/86";
36  */
37 
38 /************************************************************************
39  *									*
40  *	  Licensed from Digital Equipment Corporation			*
41  *			 Copyright (c)					*
42  *		 Digital Equipment Corporation				*
43  *		     Maynard, Massachusetts				*
44  *			   1985, 1986					*
45  *		      All rights reserved.				*
46  *									*
47  *	  The Information in this software is subject to change		*
48  *   without notice and should not be construed as a commitment		*
49  *   by	 Digital  Equipment  Corporation.   Digital   makes  no		*
50  *   representations about the suitability of this software for		*
51  *   any purpose.  It is supplied "As Is" without expressed  or		*
52  *   implied  warranty.							*
53  *									*
54  *	  If the Regents of the University of California or its		*
55  *   licensees modify the software in a manner creating			*
56  *   derivative copyright rights, appropriate copyright			*
57  *   legends may be placed on  the derivative work in addition		*
58  *   to that set forth above.						*
59  *									*
60  ************************************************************************/
61 
62 /*
63  * TSV05/TS05 device driver, written by Bertram Barth.
64  *
65  * should be TS11 compatible (untested)
66  */
67 
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: ts.c,v 1.33 2019/12/08 19:52:37 ad Exp $");
70 
71 #undef	TSDEBUG
72 
73 /*
74  * TODO:
75  *
76  * Keep track of tape position so that lseek et al works.
77  * Use tprintf to inform the user, not the system console.
78  */
79 
80 
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/kernel.h>
84 #include <sys/buf.h>
85 #include <sys/bufq.h>
86 #include <sys/conf.h>
87 #include <sys/device.h>
88 #include <sys/errno.h>
89 #include <sys/file.h>
90 #include <sys/syslog.h>
91 #include <sys/ioctl.h>
92 #include <sys/mtio.h>
93 #include <sys/uio.h>
94 #include <sys/proc.h>
95 
96 #include <sys/bus.h>
97 
98 #include <dev/qbus/ubareg.h>
99 #include <dev/qbus/ubavar.h>
100 
101 #include <dev/qbus/tsreg.h>
102 
103 #include "ioconf.h"
104 
105 struct ts {
106 	struct cmd cmd;	/* command packet */
107 	struct chr chr;	/* characteristics packet */
108 	struct status status;	/* status packet */
109 };
110 
111 /*
112  * Software status, per controller.
113  * also status per tape-unit, since only one unit per controller
114  * (thus we have no struct ts_info)
115  */
116 struct ts_softc {
117 	device_t sc_dev;		/* Autoconf ... */
118 	struct uba_softc *sc_uh;	/* the parent UBA */
119 	struct uba_unit sc_unit;	/* Struct common for UBA to talk */
120 	struct evcnt sc_intrcnt;	/* Interrupt counting */
121 	struct ubinfo sc_ui;		/* mapping info for struct ts */
122 	struct uba_unit sc_uu;		/* Struct for UBA to communicate */
123 	bus_space_tag_t sc_iot;
124 	bus_addr_t sc_ioh;
125 	bus_dma_tag_t sc_dmat;
126 	bus_dmamap_t sc_dmam;
127 	volatile struct ts *sc_vts;	/* Memory address of ts struct */
128 	struct ts *sc_bts;		/* Unibus address of ts struct */
129 	int	sc_type;		/* TS11 or TS05? */
130 	short	sc_waddr;		/* Value to write to TSDB */
131 	struct bufq_state *sc_bufq;	/* pending I/O requests */
132 
133 	short	sc_mapped;		/* Unibus map allocated ? */
134 	short	sc_state;		/* see below: ST_xxx */
135 	short	sc_rtc;			/* retry count for lcmd */
136 	short	sc_openf;		/* lock against multiple opens */
137 	short	sc_liowf;		/* last operation was write */
138 	struct buf ts_cbuf;		/* internal cmd buffer (for ioctls) */
139 };
140 
141 #define	TS_WCSR(csr, val) \
142 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
143 #define TS_RCSR(csr) \
144 	bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
145 
146 #define LOWORD(x)	((int)(x) & 0xffff)
147 #define HIWORD(x)	(((int)(x) >> 16) & 0x3f)
148 
149 #define	TYPE_TS11	0
150 #define	TYPE_TS05	1
151 #define	TYPE_TU80	2
152 
153 #define	TS_INVALID	0
154 #define	TS_INIT		1
155 #define	TS_RUNNING	2
156 #define	TS_FASTREPOS	3
157 
158 static	void tsintr(void *);
159 static	void tsinit(struct ts_softc *);
160 static	void tscommand(struct ts_softc *, dev_t, int, int);
161 static	int tsstart(struct ts_softc *, int);
162 static	void tswchar(struct ts_softc *);
163 static	bool tsreset(struct ts_softc *);
164 static	int tsmatch(device_t, cfdata_t, void *);
165 static	void tsattach(device_t, device_t, void *);
166 static	int tsready(struct uba_unit *);
167 
168 CFATTACH_DECL_NEW(ts, sizeof(struct ts_softc),
169     tsmatch, tsattach, NULL, NULL);
170 
171 dev_type_open(tsopen);
172 dev_type_close(tsclose);
173 dev_type_read(tsread);
174 dev_type_write(tswrite);
175 dev_type_ioctl(tsioctl);
176 dev_type_strategy(tsstrategy);
177 dev_type_dump(tsdump);
178 
179 const struct bdevsw ts_bdevsw = {
180 	.d_open = tsopen,
181 	.d_close = tsclose,
182 	.d_strategy = tsstrategy,
183 	.d_ioctl = tsioctl,
184 	.d_dump = tsdump,
185 	.d_psize = nosize,
186 	.d_discard = nodiscard,
187 	.d_flag = D_TAPE
188 };
189 
190 const struct cdevsw ts_cdevsw = {
191 	.d_open = tsopen,
192 	.d_close = tsclose,
193 	.d_read = tsread,
194 	.d_write = tswrite,
195 	.d_ioctl = tsioctl,
196 	.d_stop = nostop,
197 	.d_tty = notty,
198 	.d_poll = nopoll,
199 	.d_mmap = nommap,
200 	.d_kqfilter = nokqfilter,
201 	.d_discard = nodiscard,
202 	.d_flag = D_TAPE
203 };
204 
205 /* Bits in minor device */
206 #define TS_UNIT(dev)	(minor(dev)&03)
207 #define TS_HIDENSITY	010
208 
209 #define TS_PRI	LOG_INFO
210 
211 
212 /*
213  * Probe for device. If found, try to raise an interrupt.
214  */
215 int
216 tsmatch(device_t parent, cfdata_t match, void *aux)
217 {
218 	struct device tsdev;
219 	struct ts_softc ssc;
220 	struct ts_softc *sc = &ssc;
221 	struct uba_attach_args *ua = aux;
222 	int i;
223 
224 	sc->sc_iot = ua->ua_iot;
225 	sc->sc_ioh = ua->ua_ioh;
226 	sc->sc_mapped = 0;
227 	sc->sc_dev = &tsdev;
228 	sc->sc_uh = device_private(parent);
229 	strcpy(sc->sc_dev->dv_xname, "ts");
230 
231 	/* Try to reset the device */
232 	for (i = 0; i < 3; i++) {
233 		if (tsreset(sc))
234 			break;
235 	}
236 
237 	if (i == 3)
238 		return 0;
239 
240 	tsinit(sc);
241 	tswchar(sc);		/* write charact. to enable interrupts */
242 				/* completion of this will raise the intr. */
243 
244 	DELAY(1000000);		/* Wait for interrupt */
245 	ubmemfree(sc->sc_uh, &sc->sc_ui);
246 	return 1;
247 }
248 
249 /*
250  */
251 void
252 tsattach(device_t parent, device_t self, void *aux)
253 {
254 	struct ts_softc *sc = device_private(self);
255 	struct uba_attach_args *ua = aux;
256 	int error;
257 	const char *t;
258 
259 	sc->sc_dev = self;
260 	sc->sc_uh = device_private(parent);
261 	sc->sc_iot = ua->ua_iot;
262 	sc->sc_ioh = ua->ua_ioh;
263 	sc->sc_dmat = ua->ua_dmat;
264 
265 	sc->sc_uu.uu_dev = self;
266 	sc->sc_uu.uu_ready = tsready;
267 
268 	tsinit(sc);	/* reset and map */
269 
270 	error = bus_dmamap_create(sc->sc_dmat, (64*1024), 16, (64*1024),
271 	    0, BUS_DMA_NOWAIT, &sc->sc_dmam);
272 	if (error) {
273 		aprint_error(": failed create DMA map %d\n", error);
274 		return;
275 	}
276 
277 	bufq_alloc(&sc->sc_bufq, "fcfs", 0);
278 
279 	/*
280 	 * write the characteristics (again)
281 	 */
282 	sc->sc_state = TS_INIT;		/* tsintr() checks this ... */
283 	tswchar(sc);
284 	if (tsleep(sc, PRIBIO, "tsattach", 100)) {
285 		aprint_error(": failed SET CHARACTERISTICS\n");
286 		return;
287 	}
288 
289 	sc->sc_state = TS_RUNNING;
290 	if (sc->sc_uh->uh_type == UBA_UBA) {
291 		if (sc->sc_vts->status.xst2 & TS_SF_TU80) {
292 			sc->sc_type = TYPE_TU80;
293 			t = "TU80";
294 		} else {
295 			sc->sc_type = TYPE_TS11;
296 			t = "TS11";
297 		}
298 	} else {
299 		sc->sc_type = TYPE_TS05;
300 		t = "TS05";
301 	}
302 
303 	aprint_normal(": %s\n", t);
304 	aprint_normal_dev(sc->sc_dev,
305 	    "rev %d, extended features %s, transport %s\n",
306 	    (sc->sc_vts->status.xst2 & TS_SF_MCRL) >> 2,
307 	    (sc->sc_vts->status.xst2 & TS_SF_EFES ? "enabled" : "disabled"),
308 	    (TS_RCSR(TSSR) & TS_OFL ? "offline" : "online"));
309 
310 	uba_intr_establish(ua->ua_icookie, ua->ua_cvec, tsintr,
311 	    sc, &sc->sc_intrcnt);
312 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
313 	    device_xname(sc->sc_dev), "intr");
314 }
315 
316 /*
317  * Initialize a TS device. Set up UBA mapping registers,
318  * initialize data structures, what else ???
319  */
320 void
321 tsinit(struct ts_softc *sc)
322 {
323 	if (sc->sc_mapped == 0) {
324 
325 		/*
326 		 * Map the communications area and command and message
327 		 * buffer into Unibus address space.
328 		 */
329 		sc->sc_ui.ui_size = sizeof(struct ts);
330 		if (ubmemalloc(sc->sc_uh, &sc->sc_ui, UBA_CANTWAIT))
331 			return;
332 		sc->sc_vts = (void *)sc->sc_ui.ui_vaddr;
333 		sc->sc_bts = (void *)sc->sc_ui.ui_baddr;
334 		sc->sc_waddr = sc->sc_ui.ui_baddr |
335 		    ((sc->sc_ui.ui_baddr >> 16) & 3);
336 		sc->sc_mapped = 1;
337 	}
338 	tsreset(sc);
339 }
340 
341 /*
342  * Execute a (ioctl) command on the tape drive a specified number of times.
343  * This routine sets up a buffer and calls the strategy routine which
344  * issues the command to the controller.
345  */
346 void
347 tscommand(struct ts_softc *sc, dev_t dev, int cmd, int count)
348 {
349 	struct buf *bp;
350 
351 #ifdef TSDEBUG
352 	printf("tscommand (%x, %d)\n", cmd, count);
353 #endif
354 
355 	bp = &sc->ts_cbuf;
356 
357 	mutex_enter(&bufcache_lock);
358 	while (bp->b_cflags & BC_BUSY) {
359 		/*
360 		 * This special check is because BC_BUSY never
361 		 * gets cleared in the non-waiting rewind case. ???
362 		 */
363 		if (bp->b_bcount == 0 && (bp->b_oflags & BO_DONE))
364 			break;
365 		if (bbusy(bp, false, 0, NULL) == 0)
366 			break;
367 		/* check MOT-flag !!! */
368 	}
369 	bp->b_flags = B_READ;
370 	mutex_exit(&bufcache_lock);
371 
372 	/*
373 	 * Load the buffer.  The b_count field gets used to hold the command
374 	 * count.  the b_resid field gets used to hold the command mneumonic.
375 	 * These 2 fields are "known" to be "safe" to use for this purpose.
376 	 * (Most other drivers also use these fields in this way.)
377 	 */
378 	bp->b_dev = dev;
379 	bp->b_bcount = count;
380 	bp->b_resid = cmd;
381 	bp->b_blkno = 0;
382 	bp->b_oflags = 0;
383 	bp->b_objlock = &buffer_lock;
384 	tsstrategy(bp);
385 	/*
386 	 * In case of rewind from close, don't wait.
387 	 * This is the only case where count can be 0.
388 	 */
389 	if (count == 0)
390 		return;
391 	biowait(bp);
392 	mutex_enter(&bufcache_lock);
393 	cv_broadcast(&bp->b_busy);
394 	bp->b_cflags = 0;
395 	mutex_exit(&bufcache_lock);
396 }
397 
398 /*
399  * Start an I/O operation on TS05 controller
400  */
401 int
402 tsstart(struct ts_softc *sc, int isloaded)
403 {
404 	struct buf *bp;
405 	int cmd;
406 
407 	bp = bufq_peek(sc->sc_bufq);
408 	if (bp == NULL) {
409 		return 0;
410 	}
411 #ifdef TSDEBUG
412 	printf("buf: %p bcount %ld blkno %d\n", bp, bp->b_bcount, bp->b_blkno);
413 #endif
414 	/*
415 	 * Check if command is an ioctl or not (ie. read or write).
416 	 * If it's an ioctl then just set the flags for later use;
417 	 * For other commands attempt to setup a buffer pointer.
418 	 */
419 	if (bp == &sc->ts_cbuf) {
420 		switch ((int)bp->b_resid) {
421 		case MTWEOF:
422 			cmd = TS_CMD_WTM;
423 			break;
424 		case MTFSF:
425 			cmd = TS_CMD_STMF;
426 			sc->sc_vts->cmd.cw1 = bp->b_bcount;
427 			break;
428 		case MTBSF:
429 			cmd = TS_CMD_STMR;
430 			sc->sc_vts->cmd.cw1 = bp->b_bcount;
431 			break;
432 		case MTFSR:
433 			cmd = TS_CMD_SRF;
434 			sc->sc_vts->cmd.cw1 = bp->b_bcount;
435 			break;
436 		case MTBSR:
437 			cmd = TS_CMD_SRR;
438 			sc->sc_vts->cmd.cw1 = bp->b_bcount;
439 			break;
440 		case MTREW:
441 			cmd = TS_CMD_RWND;
442 			break;
443 		case MTOFFL:
444 			cmd = TS_CMD_RWUL;
445 			break;
446 		case MTNOP:
447 			cmd = TS_CMD_STAT;
448 			break;
449 		default:
450 			aprint_error_dev(sc->sc_dev, "bad ioctl %d\n",
451 				(int)bp->b_resid);
452 			/* Need a no-op. get status */
453 			cmd = TS_CMD_STAT;
454 		} /* end switch (bp->b_resid) */
455 	} else {
456 		if (isloaded == 0) {
457 			/*
458 			 * now we try to map the buffer into uba map space (???)
459 			 */
460 			if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam,
461 			    bp->b_data,
462 			    bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT)) {
463 				uba_enqueue(&sc->sc_uu);
464 				return 0;
465 			}
466 			sc->sc_rtc = 0;
467 		}
468 		sc->sc_vts->cmd.cw1 = LOWORD(sc->sc_dmam->dm_segs[0].ds_addr);
469 		sc->sc_vts->cmd.cw2 = HIWORD(sc->sc_dmam->dm_segs[0].ds_addr);
470 		sc->sc_vts->cmd.cw3 = bp->b_bcount;
471 		bp->b_error = 0; /* Used for error count */
472 #ifdef TSDEBUG
473 		printf("tsstart-1: err %d\n", bp->b_error);
474 #endif
475 		if (bp->b_flags & B_READ)
476 			cmd = TS_CMD_RNF;
477 		else
478 			cmd = TS_CMD_WD;
479 	}
480 
481 	/*
482 	 * Now that the command-buffer is setup, give it to the controller
483 	 */
484 	sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | cmd;
485 #ifdef TSDEBUG
486 	printf("tsstart: sending cmdr %x\n", sc->sc_vts->cmd.cmdr);
487 #endif
488 	TS_WCSR(TSDB, sc->sc_waddr);
489 	return 1;
490 }
491 
492 /*
493  * Called when there are free uba resources.
494  */
495 int
496 tsready(struct uba_unit *uu)
497 {
498 	struct ts_softc *sc = device_private(uu->uu_dev);
499 	struct buf *bp = bufq_peek(sc->sc_bufq);
500 
501 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, bp->b_data,
502 	    bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT))
503 		return 0;
504 
505 	tsstart(sc, 1);
506 	return 1;
507 }
508 
509 /*
510  * initialize the controller by sending WRITE CHARACTERISTICS command.
511  * contents of command- and message-buffer are assembled during this
512  * function.
513  */
514 void
515 tswchar(struct ts_softc *sc)
516 {
517 	/*
518 	 * assemble and send "WRITE CHARACTERISTICS" command
519 	 */
520 
521 	sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR;
522 	sc->sc_vts->cmd.cw1  = LOWORD(&sc->sc_bts->chr);
523 	sc->sc_vts->cmd.cw2  = HIWORD(&sc->sc_bts->chr);
524 	sc->sc_vts->cmd.cw3  = 010;		   /* size of charact.-data */
525 
526 	sc->sc_vts->chr.sadrl = LOWORD(&sc->sc_bts->status);
527 	sc->sc_vts->chr.sadrh = HIWORD(&sc->sc_bts->status);
528 	sc->sc_vts->chr.onesix = (sc->sc_type == TYPE_TS05 ? 020 : 016);
529 	sc->sc_vts->chr.chrw = TS_WC_ESS;
530 	sc->sc_vts->chr.xchrw = TS_WCX_HSP|TS_WCX_RBUF|TS_WCX_WBUF;
531 
532 	TS_WCSR(TSDB, sc->sc_waddr);
533 }
534 
535 /*
536  * Reset the TS11. Return 1 if failed, 0 if succeeded.
537  */
538 bool
539 tsreset(struct ts_softc *sc)
540 {
541 	int timeout;
542 
543 	/*
544 	 * reset ctlr by writing into TSSR, then write characteristics
545 	 */
546 	timeout = 0;		/* timeout in 10 seconds */
547 	TS_WCSR(TSSR, 0);	/* start initialization */
548 	while ((TS_RCSR(TSSR) & TS_SSR) == 0) {
549 		DELAY(10000);
550 		if (timeout++ > 1000)
551 			return false;
552 	}
553 	return true;
554 }
555 
556 static void
557 prtstat(struct ts_softc *sc, int sr)
558 {
559 	char buf[100];
560 
561 	snprintb(buf, sizeof(buf), TS_TSSR_BITS, sr);
562 	aprint_normal_dev(sc->sc_dev, "TSSR=%s\n", buf);
563 	snprintb(buf, sizeof(buf), TS_XST0_BITS, sc->sc_vts->status.xst0);
564 	aprint_normal_dev(sc->sc_dev, "XST0=%s\n", buf);
565 }
566 
567 /*
568  * TSV05/TS05 interrupt routine
569  */
570 static void
571 tsintr(void *arg)
572 {
573 	struct ts_softc *sc = arg;
574 	struct buf *bp;
575 
576 	unsigned short sr = TS_RCSR(TSSR);	/* save TSSR */
577 	unsigned short mh = sc->sc_vts->status.hdr;	/* and msg-header */
578 		/* clear the message header ??? */
579 
580 	short ccode = sc->sc_vts->cmd.cmdr & TS_CF_CCODE;
581 
582 	bp = bufq_peek(sc->sc_bufq);
583 #ifdef TSDEBUG
584 	{
585 		char buf[100];
586 		snprintb(buf, sizeof(buf), TS_TSSR_BITS, sr);
587 		printf("tsintr: sr %x mh %x\n", sr, mh);
588 		printf("srbits: %s\n", buf);
589 	}
590 #endif
591 	/*
592 	 * There are two different things which can (and should) be checked:
593 	 * the actual (internal) state and the device's result (tssr/msg.hdr)
594 	 *
595 	 * For each state there's only one "normal" interrupt. Anything else
596 	 * has to be checked more intensively. Thus in a first run according
597 	 * to the internal state the expected interrupt is checked/handled.
598 	 *
599 	 * In a second run the remaining (not yet handled) interrupts are
600 	 * checked according to the drive's result.
601 	 */
602 	switch (sc->sc_state) {
603 
604 	case TS_INVALID:
605 		/*
606 		 * Ignore unsolicited interrupts.
607 		 */
608 		log(LOG_WARNING, "%s: stray intr [%x,%x]\n",
609 			device_xname(sc->sc_dev), sr, mh);
610 		return;
611 
612 	case TS_INIT:
613 		/*
614 		 * Init phase ready.
615 		 */
616 		wakeup(sc);
617 		return;
618 
619 	case TS_RUNNING:
620 	case TS_FASTREPOS:
621 		/*
622 		 * Here we expect interrupts indicating the end of
623 		 * commands or indicating problems.
624 		 */
625 		/*
626 		 * Anything else is handled outside this switch ...
627 		 */
628 		break;
629 
630 	default:
631 		aprint_error_dev(sc->sc_dev,
632 		    "unexpected interrupt during state %d [%x,%x]\n",
633 		    sc->sc_state, sr, mh);
634 		return;
635 	}
636 
637 	/*
638 	 * now we check the termination class.
639 	 */
640 	switch (sr & TS_TC) {
641 
642 	case TS_TC_NORM:
643 		/*
644 		 * Normal termination -- The operation is completed
645 		 * witout incident.
646 		 */
647 		if (sc->sc_state == TS_FASTREPOS) {
648 #ifdef TSDEBUG
649 			printf("Fast repos interrupt\n");
650 #endif
651 			/* Fast repos succeeded, start normal data xfer */
652 			sc->sc_state = TS_RUNNING;
653 			tsstart(sc, 1);
654 			return;
655 		}
656 		sc->sc_liowf = (ccode == TS_CC_WRITE);
657 		break;
658 
659 	case TS_TC_ATTN:
660 		/*
661 		 * Attention condition -- this code indicates that the
662 		 * drive has undergone a status change, such as going
663 		 * off-line or coming on-line.
664 		 * (Without EAI enabled, no Attention interrupts occur.
665 		 * drive status changes are signaled by the VCK flag.)
666 		 */
667 		return;
668 
669 	case TS_TC_TSA:
670 		/*
671 		 * Tape Status Alert -- A status condition is encountered
672 		 * that may have significance to the program. Bits of
673 		 * interest in the extended status registers include
674 		 * TMK, EOT and RLL.
675 		 */
676 #ifdef TSDEBUG
677 		{
678 			char buf[100];
679 			snprintb(buf, sizeof(buf),
680 			    TS_XST0_BITS, sc->sc_vts->status.xst0);
681 			printf("TSA: sr %x bits %s\n",
682 			    sc->sc_vts->status.xst0, buf);
683 		}
684 #endif
685 		if (sc->sc_vts->status.xst0 & TS_SF_TMK) {
686 #ifdef TSDEBUG
687 			printf(("Tape Mark detected"));
688 #endif
689 			/* Read to end-of-file. No error. */
690 			break;
691 		}
692 		if (sc->sc_vts->status.xst0 & TS_SF_EOT) {
693 			/* End of tape. Bad. */
694 #ifdef TSDEBUG
695 			printf("TS_TC_TSA: EOT\n");
696 #endif
697 			if (bp != NULL)
698 				bp->b_error = EIO;
699 			break;
700 		}
701 		if (sc->sc_vts->status.xst0 & TS_SF_RLS)
702 			break;
703 #ifndef TSDEBUG
704 		{
705 			char buf[100];
706 			snprintb(buf, sizeof(buf),
707 			    TS_XST0_BITS, sc->sc_vts->status.xst0);
708 			printf("TSA: sr %x bits %s\n",
709 			    sc->sc_vts->status.xst0, buf);
710 		}
711 #endif
712 		break;
713 
714 	case TS_TC_FR:
715 		/*
716 		 * Function Reject -- The specified function was not
717 		 * initiated. Bits of interest include OFL, VCK, BOT,
718 		 * WLE, ILC and ILA.
719 		 */
720 		if (sr & TS_OFL)
721 			printf("tape is off-line.\n");
722 #ifdef TSDEBUG
723 		{
724 			char buf[100];
725 			snprintb(buf, sizeof(buf),
726 			    TS_XST0_BITS, sc->sc_vts->status.xst0);
727 			printf("FR: sr %x bits %s\n",
728 			    sc->sc_vts->status.xst0, buf);
729 		}
730 #endif
731 		if (sc->sc_vts->status.xst0 & TS_SF_VCK)
732 			printf("Volume check\n");
733 		if (sc->sc_vts->status.xst0 & TS_SF_BOT)
734 			printf("Start of tape.\n");
735 		if (sc->sc_vts->status.xst0 & TS_SF_WLE)
736 			printf("Write Lock Error\n");
737 		if (sc->sc_vts->status.xst0 & TS_SF_EOT)
738 			printf("End of tape.\n");
739 		break;
740 
741 	case TS_TC_TPD:
742 		/*
743 		 * Recoverable Error -- Tape position is a record beyond
744 		 * what its position was when the function was initiated.
745 		 * Suggested recovery procedure is to log the error and
746 		 * issue the appropriate retry command.
747 		 *
748 		 * Do a fast repositioning one record back.
749 		 */
750 		sc->sc_state = TS_FASTREPOS;
751 #ifdef TSDEBUG
752 		printf("TS_TC_TPD: errcnt %d\n", sc->sc_rtc);
753 #endif
754 		if (sc->sc_rtc++ == 8) {
755 			aprint_error_dev(sc->sc_dev, "failed 8 retries\n");
756 			prtstat(sc, sr);
757 			if (bp != NULL)
758 				bp->b_error = EIO;
759 			break;
760 		}
761 		sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_SRR;
762 		sc->sc_vts->cmd.cw1 = 1;
763 		TS_WCSR(TSDB, sc->sc_waddr);
764 		return;
765 
766 	case TS_TC_TNM:
767 		/*
768 		 * Recoverable Error -- Tape position has not changed.
769 		 * Suggested recovery procedure is to log the error and
770 		 * reissue the original command.
771 		 */
772 		if (sc->sc_rtc++ == 8) {
773 			aprint_error_dev(sc->sc_dev, "failed 8 retries\n");
774 			prtstat(sc, sr);
775 			if (bp != NULL)
776 				bp->b_error = EIO;
777 			break;
778 		}
779 		tsstart(sc, 1);
780 		return;
781 
782 	case TS_TC_TPL:
783 		/*
784 		 * Unrecoverable Error -- Tape position has been lost.
785 		 * No valid recovery procedures exist unless the tape
786 		 * has labels or sequence numbers.
787 		 */
788 		aprint_error_dev(sc->sc_dev, "tape position lost\n");
789 		if (bp != NULL)
790 			bp->b_error = EIO;
791 		break;
792 
793 	case TS_TC_FCE:
794 		/*
795 		 * Fatal subsytem Error -- The subsytem is incapable
796 		 * of properly performing commands, or at least its
797 		 * integrity is seriously questionable. Refer to the
798 		 * fatal class code field in the TSSR register for
799 		 * additional information on the type of fatal error.
800 		 */
801 		aprint_error_dev(sc->sc_dev, "fatal controller error\n");
802 		prtstat(sc, sr);
803 		break;
804 
805 	default:
806 		aprint_error_dev(sc->sc_dev,
807 		    "error 0x%x, resetting controller\n", sr & TS_TC);
808 		tsreset(sc);
809 	}
810 	if ((bp = bufq_get(sc->sc_bufq)) != NULL) {
811 #ifdef TSDEBUG
812 		printf("tsintr2: que %p\n", bufq_peek(sc->sc_bufq));
813 #endif
814 		if (bp != &sc->ts_cbuf) {	/* no ioctl */
815 			bus_dmamap_unload(sc->sc_dmat, sc->sc_dmam);
816 			uba_done(sc->sc_uh);
817 		}
818 		bp->b_resid = sc->sc_vts->status.rbpcr;
819 		biodone (bp);
820 	}
821 	tsstart(sc, 0);
822 }
823 
824 
825 /*
826  * Open a ts device and set the unit online.  If the controller is not
827  * in the run state, call init to initialize the ts controller first.
828  */
829 int
830 tsopen(dev_t dev, int flag, int type, struct lwp *l)
831 {
832 	struct ts_softc *sc = device_lookup_private(&ts_cd, TS_UNIT(dev));
833 
834 	if (sc == NULL)
835 		return ENXIO;
836 
837 	if (sc->sc_state < TS_RUNNING)
838 		return ENXIO;
839 
840 	if (sc->sc_openf)
841 		return EBUSY;
842 	sc->sc_openf = 1;
843 
844 	/*
845 	 * check if transport is really online.
846 	 * (without attention-interrupts enabled, we really don't know
847 	 * the actual state of the transport. Thus we call get-status
848 	 * (ie. MTNOP) once and check the actual status.)
849 	 */
850 	if (TS_RCSR(TSSR) & TS_OFL) {
851 		uprintf("%s: transport is offline.\n", device_xname(sc->sc_dev));
852 		sc->sc_openf = 0;
853 		return EIO;		/* transport is offline */
854 	}
855 	tscommand(sc, dev, MTNOP, 1);
856 	if ((flag & FWRITE) && (sc->sc_vts->status.xst0 & TS_SF_WLK)) {
857 		uprintf("%s: no write ring.\n", device_xname(sc->sc_dev));
858 		sc->sc_openf = 0;
859 		return EROFS;
860 	}
861 	if (sc->sc_vts->status.xst0 & TS_SF_VCK) {
862 		sc->sc_vts->cmd.cmdr = TS_CF_CVC|TS_CF_ACK;
863 		TS_WCSR(TSDB, sc->sc_waddr);
864 	}
865 	tscommand(sc, dev, MTNOP, 1);
866 #ifdef TSDEBUG
867 	{
868 		char buf[100];
869 		snprintb(buf, sizeof(buf),
870 		    TS_XST0_BITS, sc->sc_vts->status.xst0);
871 		printf("tsopen: xst0 %s\n", buf);
872 	}
873 #endif
874 	sc->sc_liowf = 0;
875 	return 0;
876 }
877 
878 
879 /*
880  * Close tape device.
881  *
882  * If tape was open for writing or last operation was
883  * a write, then write two EOF's and backspace over the last one.
884  * Unless this is a non-rewinding special file, rewind the tape.
885  *
886  * Make the tape available to others, by clearing openf flag.
887  */
888 int
889 tsclose(dev_t dev, int flag, int type, struct lwp *l)
890 {
891 	struct ts_softc *sc = device_lookup_private(&ts_cd, TS_UNIT(dev));
892 
893 	if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) {
894 		/*
895 		 * We are writing two tape marks (EOT), but place the tape
896 		 * before the second one, so that another write operation
897 		 * will overwrite the second one and leave and EOF-mark.
898 		 */
899 		tscommand(sc, dev, MTWEOF, 1);	/* Write Tape Mark */
900 		tscommand(sc, dev, MTWEOF, 1);	/* Write Tape Mark */
901 		tscommand(sc, dev, MTBSF, 1);	/* Skip Tape Marks Reverse */
902 	}
903 
904 	if ((dev & T_NOREWIND) == 0)
905 		tscommand(sc, dev, MTREW, 0);
906 
907 	sc->sc_openf = 0;
908 	sc->sc_liowf = 0;
909 	return 0;
910 }
911 
912 
913 /*
914  * Manage buffers and perform block mode read and write operations.
915  */
916 void
917 tsstrategy(struct buf *bp)
918 {
919 	struct ts_softc *sc = device_lookup_private(&ts_cd, TS_UNIT(bp->b_dev));
920 	bool empty;
921 	int s;
922 
923 #ifdef TSDEBUG
924 	printf("buf: %p bcount %ld blkno %d\n", bp, bp->b_bcount, bp->b_blkno);
925 #endif
926 	s = splbio ();
927 	empty = (bufq_peek(sc->sc_bufq) == NULL);
928 	bufq_put(sc->sc_bufq, bp);
929 	if (empty)
930 		tsstart(sc, 0);
931 	splx(s);
932 }
933 
934 
935 /*
936  * Catch ioctl commands, and call the "command" routine to do them.
937  */
938 int
939 tsioctl(dev_t dev,
940 	u_long cmd,
941 	void *data,
942 	int flag,
943 	struct lwp *l)
944 {
945 	struct buf *bp;
946 	struct ts_softc * const sc = device_lookup_private(&ts_cd, TS_UNIT(dev));
947 	struct mtop *mtop;	/* mag tape cmd op to perform */
948 	struct mtget *mtget;	/* mag tape struct to get info in */
949 	int callcount;		/* number of times to call routine */
950 	int scount;			/* number of files/records to space */
951 	int spaceop = 0;		/* flag for skip/space operation */
952 	int error = 0;
953 
954 #ifdef TSDEBUG
955 	printf("tsioctl (%x, %lx, %p, %d)\n", dev, cmd, data, flag);
956 #endif
957 
958 	bp = &sc->ts_cbuf;
959 
960 	switch (cmd) {
961 	case MTIOCTOP:			/* do a mag tape op */
962 		mtop = (struct mtop *)data;
963 		switch (mtop->mt_op) {
964 		case MTWEOF:		/* write an end-of-file record */
965 			callcount = mtop->mt_count;
966 			scount = 1;
967 			break;
968 		case MTFSR:		/* forward space record */
969 		case MTBSR:		/* backward space record */
970 			spaceop = 1;
971 		case MTFSF:		/* forward space file */
972 		case MTBSF:		/* backward space file */
973 			callcount = 1;
974 			scount = mtop->mt_count;
975 			break;
976 		case MTREW:		/* rewind */
977 		case MTOFFL:		/* rewind and put the drive offline */
978 		case MTNOP:		/* no operation, sets status only */
979 			callcount = 1;
980 			scount = 1;		/* wait for this rewind */
981 			break;
982 		case MTRETEN:		/* retension */
983 		case MTERASE:		/* erase entire tape */
984 		case MTEOM:		/* forward to end of media */
985 		case MTNBSF:		/* backward space to begin of file */
986 		case MTCACHE:		/* enable controller cache */
987 		case MTNOCACHE:		/* disable controller cache */
988 		case MTSETBSIZ:		/* set block size; 0 for variable */
989 		case MTSETDNSTY:	/* set density code for current mode */
990 			printf("ioctl %d not implemented.\n", mtop->mt_op);
991 			return (ENXIO);
992 		default:
993 #ifdef TSDEBUG
994 			printf("invalid ioctl %d\n", mtop->mt_op);
995 #endif
996 			return (ENXIO);
997 		}	/* switch (mtop->mt_op) */
998 
999 		if (callcount <= 0 || scount <= 0) {
1000 #ifdef TSDEBUG
1001 			printf("invalid values %d/%d\n", callcount, scount);
1002 #endif
1003 			return (EINVAL);
1004 		}
1005 		do {
1006 			tscommand(sc, dev, mtop->mt_op, scount);
1007 			if (spaceop && bp->b_resid) {
1008 #ifdef TSDEBUG
1009 				printf(("spaceop didn't complete\n"));
1010 #endif
1011 				return (EIO);
1012 			}
1013 			if (bp->b_error != 0) {
1014 #ifdef TSDEBUG
1015 				printf("error in ioctl %d\n", mtop->mt_op);
1016 #endif
1017 				break;
1018 			}
1019 		} while (--callcount > 0);
1020 		if (bp->b_error != 0)
1021 			error = bp->b_error;
1022 		return (error);
1023 
1024 	case MTIOCGET:			/* get tape status */
1025 		mtget = (struct mtget *)data;
1026 		mtget->mt_type = MT_ISTS;
1027 		mtget->mt_dsreg = TS_RCSR(TSSR);
1028 		mtget->mt_erreg = sc->sc_vts->status.xst0;
1029 		mtget->mt_resid = 0;		/* ??? */
1030 		mtget->mt_density = 0;		/* ??? */
1031 		break;
1032 
1033 	case MTIOCIEOT:			/* ignore EOT error */
1034 #ifdef TSDEBUG
1035 		printf(("MTIOCIEOT not implemented.\n"));
1036 #endif
1037 		return (ENXIO);
1038 
1039 	case MTIOCEEOT:			/* enable EOT error */
1040 #ifdef TSDEBUG
1041 		printf(("MTIOCEEOT not implemented.\n"));
1042 #endif
1043 		return (ENXIO);
1044 
1045 	default:
1046 #ifdef TSDEBUG
1047 		printf("invalid ioctl cmd 0x%lx\n", cmd);
1048 #endif
1049 		return (ENXIO);
1050 	}
1051 
1052 	return (0);
1053 }
1054 
1055 
1056 /*
1057  *
1058  */
1059 int
1060 tsread(dev_t dev, struct uio *uio, int flag)
1061 {
1062 	return (physio (tsstrategy, NULL, dev, B_READ, minphys, uio));
1063 }
1064 
1065 /*
1066  *
1067  */
1068 int
1069 tswrite(dev_t dev, struct uio *uio, int flag)
1070 {
1071 	return (physio (tsstrategy, NULL, dev, B_WRITE, minphys, uio));
1072 }
1073 
1074 /*
1075  *
1076  */
1077 int
1078 tsdump(dev_t dev, daddr_t blkno, void *va, size_t size)
1079 {
1080 	return EIO;
1081 }
1082