xref: /original-bsd/sys/vax/stand/mt.c (revision 2ce9ec30)
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.3 (Berkeley) 02/22/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 struct mtdevice *mtaddr;
34 	register int i, skip;
35 
36 	if (mbainit(io->i_adapt) == 0)
37 		return (EADAPT);
38 	mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr);
39 	for (i = 0;; i++) {
40 		if (!mttypes[i]) {
41 			printf("mt: not a tape\n");
42 			return (ENXIO);
43 		}
44 		if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE))
45 			break;
46 	}
47 	mtaddr->mtid = MTID_CLR;
48 	DELAY(250);
49 	while ((mtaddr->mtid & MTID_RDY) == 0);
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 	for (skip = io->i_part; skip--;) {
57 		io->i_cc = -1;
58 		mtstrategy(io, MT_SFORWF);
59 	}
60 	return (0);
61 }
62 
63 mtclose(io)
64 	register struct iob *io;
65 {
66 	mtstrategy(io, MT_REW);
67 }
68 
69 mtstrategy(io, func)
70 	register struct iob *io;
71 	int func;
72 {
73 	register int errcnt, s, ic;
74 	register struct mtdevice *mtaddr;
75 	struct mba_regs *mba;
76 
77 	errcnt = 0;
78 	mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr);
79 	mba = mbamba(io->i_adapt);
80 retry:
81 	/* code to trap for attention up prior to start of command */
82 	if ((mtaddr->mtas & 0xffff) != 0) {
83 		printf("mt unexpected attention er=%x - continuing\n",
84 			MASKREG(mtaddr->mtner));
85 		mtaddr->mtas = mtaddr->mtas;
86 	}
87 
88 	if (func == READ || func == WRITE) {
89 		mtaddr->mtca = 1<<2;	/* 1 record */
90 		mtaddr->mtbc = io->i_cc;
91 		mbastart(io, io->i_ctlr, func);
92 		/* wait for mba to go idle and read result status */
93 		while((mba->mba_sr & MBSR_DTBUSY) != 0)
94 			;
95 		ic = mtaddr->mter & MTER_INTCODE;
96 	} else {
97 		mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO;
98 	rwait:
99 		do
100 			s = mtaddr->mtas&0xffff;
101 		while (s == 0);
102 		ic = mtaddr->mtner & MTER_INTCODE;
103 		mtaddr->mtas = mtaddr->mtas;	/* clear attention */
104 	}
105 	switch (ic) {
106 	case MTER_TM:
107 	case MTER_EOT:
108 	case MTER_LEOT:
109 		return (0);
110 
111 	case MTER_DONE:
112 		/* make sure a record was read */
113 		if ((mtaddr->mtca & (1 << 2)) != 0) {
114 			printf("mt record count not decremented - retrying\n");
115 			goto retry;
116 		}
117 		break;
118 
119 	case MTER_RWDING:
120 		goto rwait;
121 	default:
122 		printf("mt hard error: er=%x\n",
123 		    MASKREG(mtaddr->mter));
124 		mtaddr->mtid = MTID_CLR;
125 		DELAY(250);
126 		while ((mtaddr->mtid & MTID_RDY) == 0)
127 			;
128 		return (-1);
129 
130 	case MTER_RETRY:
131 		printf("mt error: er=%x\n", MASKREG(mtaddr->mter));
132 		if (errcnt++ == 10) {
133 			printf("mt: unrecovered error\n");
134 			return (-1);
135 		}
136 		goto retry;
137 	}
138 	if (errcnt)
139 		printf("mt: recovered by retry\n");
140 	return (io->i_cc);	/* NO PARTIAL RECORD READS!!! */
141 }
142