xref: /original-bsd/sys/vax/stand/mt.c (revision 93152bbe)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)mt.c	7.7 (Berkeley) 05/04/91
7  */
8 
9 /*
10  * TM78/TU78 tape driver
11  * Made to work reliably by by Jeffrey R. Schwab (Purdue)
12  */
13 #include "../include/pte.h"
14 
15 #include "sys/param.h"
16 
17 #include "../mba/mtreg.h"
18 #include "../mba/mbareg.h"
19 
20 #include "stand/saio.h"
21 #include "savax.h"
22 
23 short	mttypes[] =
24 	{ MBDT_TU78, 0 };
25 
26 #define	MASKREG(reg)	((reg)&0xffff)
27 
28 mtopen(io)
29 	register struct iob *io;
30 {
31 	register struct mtdevice *mtaddr;
32 	register int i, skip;
33 
34 	if (mbainit(io->i_adapt) == 0)
35 		return (EADAPT);
36 	mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr);
37 	for (i = 0;; i++) {
38 		if (!mttypes[i]) {
39 			printf("mt: not a tape\n");
40 			return (ENXIO);
41 		}
42 		if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE))
43 			break;
44 	}
45 	mtaddr->mtid = MTID_CLR;
46 	DELAY(250);
47 	while ((mtaddr->mtid & MTID_RDY) == 0);
48 
49 	/* clear any attention bits present on open */
50 	i = mtaddr->mtner;
51 	mtaddr->mtas = mtaddr->mtas;
52 
53 	mtstrategy(io, MT_REW);
54 	for (skip = io->i_part; skip--;) {
55 		io->i_cc = -1;
56 		mtstrategy(io, MT_SFORWF);
57 	}
58 	return (0);
59 }
60 
61 mtclose(io)
62 	register struct iob *io;
63 {
64 	mtstrategy(io, MT_REW);
65 }
66 
67 mtstrategy(io, func)
68 	register struct iob *io;
69 	int func;
70 {
71 	register int errcnt, s, ic;
72 	register struct mtdevice *mtaddr;
73 	struct mba_regs *mba;
74 
75 	errcnt = 0;
76 	mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr);
77 	mba = mbamba(io->i_adapt);
78 retry:
79 	/* code to trap for attention up prior to start of command */
80 	if ((mtaddr->mtas & 0xffff) != 0) {
81 		printf("mt unexpected attention er=%x - continuing\n",
82 			MASKREG(mtaddr->mtner));
83 		mtaddr->mtas = mtaddr->mtas;
84 	}
85 
86 	if (func == F_READ || func == F_WRITE) {
87 		mtaddr->mtca = 1<<2;	/* 1 record */
88 		mtaddr->mtbc = io->i_cc;
89 		mbastart(io, io->i_ctlr, func);
90 		/* wait for mba to go idle and read result status */
91 		while((mba->mba_sr & MBSR_DTBUSY) != 0)
92 			;
93 		ic = mtaddr->mter & MTER_INTCODE;
94 	} else {
95 		mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO;
96 	rwait:
97 		do
98 			s = mtaddr->mtas&0xffff;
99 		while (s == 0);
100 		ic = mtaddr->mtner & MTER_INTCODE;
101 		mtaddr->mtas = mtaddr->mtas;	/* clear attention */
102 	}
103 	switch (ic) {
104 	case MTER_TM:
105 	case MTER_EOT:
106 	case MTER_LEOT:
107 		return (0);
108 
109 	case MTER_DONE:
110 		/* make sure a record was read */
111 		if ((mtaddr->mtca & (1 << 2)) != 0) {
112 			printf("mt record count not decremented - retrying\n");
113 			goto retry;
114 		}
115 		break;
116 
117 	case MTER_RWDING:
118 		goto rwait;
119 	default:
120 		printf("mt hard error: er=%x\n",
121 		    MASKREG(mtaddr->mter));
122 		mtaddr->mtid = MTID_CLR;
123 		DELAY(250);
124 		while ((mtaddr->mtid & MTID_RDY) == 0)
125 			;
126 		return (-1);
127 
128 	case MTER_RETRY:
129 		printf("mt error: er=%x\n", MASKREG(mtaddr->mter));
130 		if (errcnt++ == 10) {
131 			printf("mt: unrecovered error\n");
132 			return (-1);
133 		}
134 		goto retry;
135 	}
136 	if (errcnt)
137 		printf("mt: recovered by retry\n");
138 	return (io->i_cc);	/* NO PARTIAL RECORD READS!!! */
139 }
140