Commit | Line | Data |
---|---|---|
55b4dbd0 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
55b4dbd0 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
39c71180 | 6 | * @(#)mt.c 7.2 (Berkeley) %G% |
55b4dbd0 | 7 | */ |
8d272394 SL |
8 | |
9 | /* | |
10 | * TM78/TU78 tape driver | |
26d5a33e | 11 | * Made to work reliably by by Jeffrey R. Schwab (Purdue) |
8d272394 | 12 | */ |
faeec66d | 13 | #include "../machine/pte.h" |
8d272394 | 14 | |
39c71180 MK |
15 | #include "param.h" |
16 | #include "inode.h" | |
17 | #include "fs.h" | |
a031a31b SL |
18 | |
19 | #include "../vaxmba/mtreg.h" | |
20 | #include "../vaxmba/mbareg.h" | |
21 | ||
8d272394 SL |
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; | |
26d5a33e SL |
34 | register struct mtdevice *mtaddr = |
35 | (struct mtdevice *)mbadrv(io->i_unit); | |
39c71180 | 36 | register int i; |
8d272394 | 37 | |
39c71180 MK |
38 | if (mbainit(UNITTOMBA(io->i_unit)) == 0) |
39 | return (ENXIO); | |
8d272394 SL |
40 | for (i = 0; mttypes[i]; i++) |
41 | if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) | |
42 | goto found; | |
39c71180 MK |
43 | printf("not a tape\n"); |
44 | return (ENXIO); | |
8d272394 | 45 | found: |
8d272394 SL |
46 | mtaddr->mtid = MTID_CLR; |
47 | DELAY(250); | |
48 | while ((mtaddr->mtid & MTID_RDY) == 0) | |
49 | ; | |
26d5a33e SL |
50 | |
51 | /* clear any attention bits present on open */ | |
52 | i = mtaddr->mtner; | |
53 | mtaddr->mtas = mtaddr->mtas; | |
54 | ||
8d272394 SL |
55 | mtstrategy(io, MT_REW); |
56 | skip = io->i_boff; | |
57 | while (skip--) { | |
58 | io->i_cc = -1; | |
59 | mtstrategy(io, MT_SFORWF); | |
60 | } | |
39c71180 | 61 | return (0); |
8d272394 SL |
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); | |
26d5a33e | 78 | struct mba_regs *mba = mbamba(io->i_unit); |
8d272394 SL |
79 | |
80 | errcnt = 0; | |
81 | retry: | |
26d5a33e SL |
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 | ||
8d272394 SL |
89 | if (func == READ || func == WRITE) { |
90 | mtaddr->mtca = 1<<2; /* 1 record */ | |
91 | mtaddr->mtbc = io->i_cc; | |
8d272394 | 92 | mbastart(io, func); |
26d5a33e SL |
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; | |
8d272394 | 97 | } else { |
8d272394 SL |
98 | mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; |
99 | rwait: | |
100 | do | |
101 | s = mtaddr->mtas&0xffff; | |
102 | while (s == 0); | |
8d272394 | 103 | ic = mtaddr->mtner & MTER_INTCODE; |
26d5a33e | 104 | mtaddr->mtas = mtaddr->mtas; /* clear attention */ |
8d272394 SL |
105 | } |
106 | switch (ic) { | |
107 | case MTER_TM: | |
108 | case MTER_EOT: | |
109 | case MTER_LEOT: | |
110 | return (0); | |
111 | ||
112 | case MTER_DONE: | |
26d5a33e SL |
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 | } | |
8d272394 SL |
118 | break; |
119 | ||
120 | case MTER_RWDING: | |
121 | goto rwait; | |
122 | default: | |
26d5a33e | 123 | printf("mt hard error: er=%x\n", |
8d272394 SL |
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: | |
26d5a33e | 132 | printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); |
8d272394 SL |
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 | } |