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