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 | * | |
c18e27ed | 6 | * @(#)mt.c 7.4 (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 | */ |
c18e27ed | 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 | { | |
1e07c79f KB |
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 | } | |
8d272394 | 44 | if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) |
1e07c79f KB |
45 | break; |
46 | } | |
8d272394 SL |
47 | mtaddr->mtid = MTID_CLR; |
48 | DELAY(250); | |
1e07c79f | 49 | while ((mtaddr->mtid & MTID_RDY) == 0); |
26d5a33e SL |
50 | |
51 | /* clear any attention bits present on open */ | |
52 | i = mtaddr->mtner; | |
53 | mtaddr->mtas = mtaddr->mtas; | |
54 | ||
8d272394 | 55 | mtstrategy(io, MT_REW); |
1e07c79f | 56 | for (skip = io->i_part; skip--;) { |
8d272394 SL |
57 | io->i_cc = -1; |
58 | mtstrategy(io, MT_SFORWF); | |
59 | } | |
39c71180 | 60 | return (0); |
8d272394 SL |
61 | } |
62 | ||
63 | mtclose(io) | |
64 | register struct iob *io; | |
65 | { | |
8d272394 SL |
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; | |
1e07c79f KB |
74 | register struct mtdevice *mtaddr; |
75 | struct mba_regs *mba; | |
8d272394 SL |
76 | |
77 | errcnt = 0; | |
1e07c79f KB |
78 | mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); |
79 | mba = mbamba(io->i_adapt); | |
8d272394 | 80 | retry: |
26d5a33e SL |
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 | ||
8d272394 SL |
88 | if (func == READ || func == WRITE) { |
89 | mtaddr->mtca = 1<<2; /* 1 record */ | |
90 | mtaddr->mtbc = io->i_cc; | |
1e07c79f | 91 | mbastart(io, io->i_ctlr, func); |
26d5a33e SL |
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; | |
8d272394 | 96 | } else { |
8d272394 SL |
97 | mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; |
98 | rwait: | |
99 | do | |
100 | s = mtaddr->mtas&0xffff; | |
101 | while (s == 0); | |
8d272394 | 102 | ic = mtaddr->mtner & MTER_INTCODE; |
26d5a33e | 103 | mtaddr->mtas = mtaddr->mtas; /* clear attention */ |
8d272394 SL |
104 | } |
105 | switch (ic) { | |
106 | case MTER_TM: | |
107 | case MTER_EOT: | |
108 | case MTER_LEOT: | |
109 | return (0); | |
110 | ||
111 | case MTER_DONE: | |
26d5a33e SL |
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 | } | |
8d272394 SL |
117 | break; |
118 | ||
119 | case MTER_RWDING: | |
120 | goto rwait; | |
121 | default: | |
26d5a33e | 122 | printf("mt hard error: er=%x\n", |
8d272394 SL |
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: | |
26d5a33e | 131 | printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); |
1e07c79f | 132 | if (errcnt++ == 10) { |
8d272394 SL |
133 | printf("mt: unrecovered error\n"); |
134 | return (-1); | |
135 | } | |
8d272394 SL |
136 | goto retry; |
137 | } | |
138 | if (errcnt) | |
139 | printf("mt: recovered by retry\n"); | |
140 | return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ | |
141 | } |