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