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
mtopen(io)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
mtclose(io)61 mtclose(io)
62 register struct iob *io;
63 {
64 mtstrategy(io, MT_REW);
65 }
66
mtstrategy(io,func)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