ts.c revision 1.33
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
105struct 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 */
116struct 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
158static	void tsintr(void *);
159static	void tsinit(struct ts_softc *);
160static	void tscommand(struct ts_softc *, dev_t, int, int);
161static	int tsstart(struct ts_softc *, int);
162static	void tswchar(struct ts_softc *);
163static	bool tsreset(struct ts_softc *);
164static	int tsmatch(device_t, cfdata_t, void *);
165static	void tsattach(device_t, device_t, void *);
166static	int tsready(struct uba_unit *);
167
168CFATTACH_DECL_NEW(ts, sizeof(struct ts_softc),
169    tsmatch, tsattach, NULL, NULL);
170
171dev_type_open(tsopen);
172dev_type_close(tsclose);
173dev_type_read(tsread);
174dev_type_write(tswrite);
175dev_type_ioctl(tsioctl);
176dev_type_strategy(tsstrategy);
177dev_type_dump(tsdump);
178
179const 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
190const 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 */
215int
216tsmatch(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 */
251void
252tsattach(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 */
320void
321tsinit(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 */
346void
347tscommand(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 */
401int
402tsstart(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 */
495int
496tsready(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 */
514void
515tswchar(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 */
538bool
539tsreset(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
556static void
557prtstat(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 */
570static void
571tsintr(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 */
829int
830tsopen(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 */
888int
889tsclose(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 */
916void
917tsstrategy(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 */
938int
939tsioctl(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 */
1059int
1060tsread(dev_t dev, struct uio *uio, int flag)
1061{
1062	return (physio (tsstrategy, NULL, dev, B_READ, minphys, uio));
1063}
1064
1065/*
1066 *
1067 */
1068int
1069tswrite(dev_t dev, struct uio *uio, int flag)
1070{
1071	return (physio (tsstrategy, NULL, dev, B_WRITE, minphys, uio));
1072}
1073
1074/*
1075 *
1076 */
1077int
1078tsdump(dev_t dev, daddr_t blkno, void *va, size_t size)
1079{
1080	return EIO;
1081}
1082