First Commit of my working state
[simh.git] / I7094 / i7094_mt.c
CommitLineData
196ba1fc
PH
1/* i7094_mt.c: IBM 7094 magnetic tape simulator\r
2\r
3 Copyright (c) 2003-2006, Robert M Supnik\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of Robert M Supnik shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from Robert M Supnik.\r
25\r
26 mt magtape simulator\r
27*/\r
28\r
29#include "i7094_defs.h"\r
30#include "sim_tape.h"\r
31\r
32#define UST u3 /* unit state */\r
33#define UCH u4 /* channel number */\r
34#define MTUF_V_LDN (MTUF_V_UF + 0)\r
35#define MTUF_LDN (1 << MTUF_V_LDN)\r
36#define MT_MAXFR ((1 << 18) + 2)\r
37\r
38#define QCHRONO(c,u) ((cpu_model & I_CT) && \\r
39 ((c) == CHRONO_CH) && ((u) == CHRONO_UNIT))\r
40\r
41uint8 *mtxb[NUM_CHAN] = { NULL }; /* xfer buffer */\r
42uint32 mt_unit[NUM_CHAN]; /* unit */\r
43uint32 mt_bptr[NUM_CHAN];\r
44uint32 mt_blnt[NUM_CHAN];\r
45t_uint64 mt_chob[NUM_CHAN];\r
46uint32 mt_chob_v[NUM_CHAN];\r
47uint32 mt_tshort = 2;\r
48uint32 mt_twef = 25000; /* 50 msec */\r
49uint32 mt_tstart = 29000; /* 58 msec */\r
50uint32 mt_tstop = 10000; /* 20 msec */\r
51uint32 mt_tword = 50; /* 125 usec */\r
52\r
53static const uint8 odd_par[64] = {\r
54 1, 0, 0, 1, 0, 1, 1, 0,\r
55 0, 1, 1, 0, 1, 0, 0, 1,\r
56 0, 1, 1, 0, 1, 0, 0, 1,\r
57 1, 0, 0, 1, 0, 1, 1, 0,\r
58 0, 1, 1, 0, 1, 0, 0, 1,\r
59 1, 0, 0, 1, 0, 1, 1, 0,\r
60 1, 0, 0, 1, 0, 1, 1, 0,\r
61 0, 1, 1, 0, 1, 0, 0, 1\r
62 };\r
63\r
64static const char *tape_stat[] = {\r
65 "OK", "TMK", "UNATT", "IOERR", "INVRECLNT",\r
66 "FMT", "BOT", "EOM", "RECERR", "WRPROT"\r
67 };\r
68\r
69extern uint32 PC;\r
70extern uint32 cpu_model;\r
71extern uint32 ind_ioc;\r
72extern FILE *sim_deb;\r
73extern char *sel_name[];\r
74\r
75t_stat mt_chsel (uint32 ch, uint32 sel, uint32 unit);\r
76t_stat mt_chwr (uint32 ch, t_uint64 val, uint32 flags);\r
77t_stat mt_rec_end (UNIT *uptr);\r
78t_stat mt_svc (UNIT *uptr);\r
79t_stat mt_reset (DEVICE *dptr);\r
80t_stat mt_attach (UNIT *uptr, char *cptr);\r
81t_stat mt_boot (int32 unitno, DEVICE *dptr);\r
82t_stat mt_map_err (UNIT *uptr, t_stat st);\r
83\r
84extern uint32 chrono_rd (uint8 *buf, uint32 bufsiz);\r
85\r
86/* MT data structures\r
87\r
88 mt_dev MT device descriptor\r
89 mt_unit MT unit list\r
90 mt_reg MT register list\r
91 mt_mod MT modifier list\r
92*/\r
93\r
94DIB mt_dib = { &mt_chsel, &mt_chwr };\r
95\r
96MTAB mt_mod[] = {\r
97 { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },\r
98 { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },\r
99 { MTUF_LDN, 0, "high density", "HIGH", NULL },\r
100 { MTUF_LDN, MTUF_LDN, "low density", "LOW", NULL },\r
101 { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",\r
102 &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },\r
103 { 0 }\r
104 };\r
105\r
106UNIT mta_unit[] = {\r
107 { UDATA (NULL, UNIT_DIS, 0) },\r
108 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
109 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
110 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
111 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
112 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
113 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
114 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
115 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
116 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
117 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
118 };\r
119\r
120REG mta_reg[] = {\r
121 { ORDATA (UNIT, mt_unit[0], 5) },\r
122 { ORDATA (CHOB, mt_chob[0], 36) },\r
123 { FLDATA (CHOBV, mt_chob_v[0], 0) },\r
124 { DRDATA (BPTR, mt_bptr[0], 16), PV_LEFT },\r
125 { DRDATA (BLNT, mt_blnt[0], 16), PV_LEFT },\r
126 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
127 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
128 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
129 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
130 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
131 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
132 { URDATA (UST, mta_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
133 { URDATA (POS, mta_unit[0].pos, 10, T_ADDR_W, 0,\r
134 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
135 { NULL }\r
136 };\r
137\r
138UNIT mtb_unit[] = {\r
139 { UDATA (NULL, UNIT_DIS, 0) },\r
140 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
141 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
142 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
143 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
144 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
145 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
146 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
147 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
148 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
149 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
150 };\r
151\r
152REG mtb_reg[] = {\r
153 { ORDATA (UNIT, mt_unit[1], 5) },\r
154 { ORDATA (CHOB, mt_chob[1], 36) },\r
155 { FLDATA (CHOBV, mt_chob_v[1], 0) },\r
156 { DRDATA (BPTR, mt_bptr[1], 16), PV_LEFT },\r
157 { DRDATA (BLNT, mt_blnt[1], 16), PV_LEFT },\r
158 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
159 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
160 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
161 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
162 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
163 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
164 { URDATA (UST, mtb_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
165 { URDATA (POS, mtb_unit[0].pos, 10, T_ADDR_W, 0,\r
166 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
167 { NULL }\r
168 };\r
169\r
170UNIT mtc_unit[] = {\r
171 { UDATA (NULL, UNIT_DIS, 0) },\r
172 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
173 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
174 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
175 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
176 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
177 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
178 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
179 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
180 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
181 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
182 };\r
183\r
184REG mtc_reg[] = {\r
185 { ORDATA (UNIT, mt_unit[2], 5) },\r
186 { ORDATA (CHOB, mt_chob[2], 36) },\r
187 { FLDATA (CHOBV, mt_chob_v[2], 0) },\r
188 { DRDATA (BPTR, mt_bptr[2], 16), PV_LEFT },\r
189 { DRDATA (BLNT, mt_blnt[2], 16), PV_LEFT },\r
190 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
191 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
192 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
193 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
194 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
195 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
196 { URDATA (UST, mtc_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
197 { URDATA (POS, mtc_unit[0].pos, 10, T_ADDR_W, 0,\r
198 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
199 { NULL }\r
200 };\r
201\r
202UNIT mtd_unit[] = {\r
203 { UDATA (NULL, UNIT_DIS, 0) },\r
204 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
205 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
206 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
207 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
208 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
209 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
210 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
211 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
212 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
213 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
214 };\r
215\r
216REG mtd_reg[] = {\r
217 { ORDATA (UNIT, mt_unit[3], 5) },\r
218 { ORDATA (CHOB, mt_chob[3], 36) },\r
219 { FLDATA (CHOBV, mt_chob_v[3], 0) },\r
220 { DRDATA (BPTR, mt_bptr[3], 16), PV_LEFT },\r
221 { DRDATA (BLNT, mt_blnt[3], 16), PV_LEFT },\r
222 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
223 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
224 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
225 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
226 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
227 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
228 { URDATA (UST, mtd_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
229 { URDATA (POS, mtd_unit[0].pos, 10, T_ADDR_W, 0,\r
230 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
231 { NULL }\r
232 };\r
233\r
234UNIT mte_unit[] = {\r
235 { UDATA (NULL, UNIT_DIS, 0) },\r
236 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
237 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
238 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
239 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
240 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
241 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
242 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
243 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
244 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
245 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
246 };\r
247\r
248REG mte_reg[] = {\r
249 { ORDATA (UNIT, mt_unit[4], 5) },\r
250 { ORDATA (CHOB, mt_chob[4], 36) },\r
251 { FLDATA (CHOBV, mt_chob_v[4], 0) },\r
252 { DRDATA (BPTR, mt_bptr[4], 16), PV_LEFT },\r
253 { DRDATA (BLNT, mt_blnt[4], 16), PV_LEFT },\r
254 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
255 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
256 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
257 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
258 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
259 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
260 { URDATA (UST, mte_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
261 { URDATA (POS, mte_unit[0].pos, 10, T_ADDR_W, 0,\r
262 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
263 { NULL }\r
264 };\r
265\r
266UNIT mtf_unit[] = {\r
267 { UDATA (NULL, UNIT_DIS, 0) },\r
268 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
269 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
270 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
271 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
272 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
273 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
274 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
275 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
276 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
277 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
278 };\r
279\r
280REG mtf_reg[] = {\r
281 { ORDATA (UNIT, mt_unit[5], 5) },\r
282 { ORDATA (CHOB, mt_chob[5], 36) },\r
283 { FLDATA (CHOBV, mt_chob_v[5], 0) },\r
284 { DRDATA (BPTR, mt_bptr[5], 16), PV_LEFT },\r
285 { DRDATA (BLNT, mt_blnt[5], 16), PV_LEFT },\r
286 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
287 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
288 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
289 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
290 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
291 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
292 { URDATA (UST, mtf_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
293 { URDATA (POS, mtf_unit[0].pos, 10, T_ADDR_W, 0,\r
294 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
295 { NULL }\r
296 };\r
297\r
298UNIT mtg_unit[] = {\r
299 { UDATA (NULL, UNIT_DIS, 0) },\r
300 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
301 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
302 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
303 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
304 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
305 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
306 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
307 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
308 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
309 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
310 };\r
311\r
312REG mtg_reg[] = {\r
313 { ORDATA (UNIT, mt_unit[6], 5) },\r
314 { ORDATA (CHOB, mt_chob[6], 36) },\r
315 { FLDATA (CHOBV, mt_chob_v[6], 0) },\r
316 { DRDATA (BPTR, mt_bptr[6], 16), PV_LEFT },\r
317 { DRDATA (BLNT, mt_blnt[6], 16), PV_LEFT },\r
318 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
319 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
320 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
321 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
322 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
323 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
324 { URDATA (UST, mtg_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
325 { URDATA (POS, mtg_unit[0].pos, 10, T_ADDR_W, 0,\r
326 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
327 { NULL }\r
328 };\r
329\r
330UNIT mth_unit[] = {\r
331 { UDATA (NULL, UNIT_DIS, 0) },\r
332 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
333 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
334 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
335 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
336 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
337 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
338 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
339 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
340 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },\r
341 { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }\r
342 };\r
343\r
344REG mth_reg[] = {\r
345 { ORDATA (UNIT, mt_unit[7], 5) },\r
346 { ORDATA (CHOB, mt_chob[7], 36) },\r
347 { FLDATA (CHOBV, mt_chob_v[7], 0) },\r
348 { DRDATA (BPTR, mt_bptr[7], 16), PV_LEFT },\r
349 { DRDATA (BLNT, mt_blnt[7], 16), PV_LEFT },\r
350 { BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },\r
351 { DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },\r
352 { DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },\r
353 { DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },\r
354 { DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },\r
355 { DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },\r
356 { URDATA (UST, mth_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },\r
357 { URDATA (POS, mth_unit[0].pos, 10, T_ADDR_W, 0,\r
358 MT_NUMDR + 1, PV_LEFT | REG_RO) },\r
359 { NULL }\r
360 };\r
361\r
362DEVICE mt_dev[NUM_CHAN] = {\r
363 {\r
364 "MTA", mta_unit, mta_reg, mt_mod,\r
365 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
366 NULL, NULL, &mt_reset,\r
367 &mt_boot, &mt_attach, &sim_tape_detach,\r
368 &mt_dib, DEV_DEBUG\r
369 },\r
370 {\r
371 "MTB", mtb_unit, mtb_reg, mt_mod,\r
372 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
373 NULL, NULL, &mt_reset,\r
374 NULL, &mt_attach, &sim_tape_detach,\r
375 &mt_dib, DEV_DIS|DEV_DEBUG\r
376 },\r
377 {\r
378 "MTC", mtc_unit, mtc_reg, mt_mod,\r
379 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
380 NULL, NULL, &mt_reset,\r
381 NULL, &mt_attach, &sim_tape_detach,\r
382 &mt_dib, DEV_DIS|DEV_DEBUG\r
383 },\r
384 {\r
385 "MTD", mtd_unit, mtd_reg, mt_mod,\r
386 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
387 NULL, NULL, &mt_reset,\r
388 NULL, &mt_attach, &sim_tape_detach,\r
389 &mt_dib, DEV_DIS|DEV_DEBUG\r
390 },\r
391 {\r
392 "MTE", mte_unit, mte_reg, mt_mod,\r
393 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
394 NULL, NULL, &mt_reset,\r
395 NULL, &mt_attach, &sim_tape_detach,\r
396 &mt_dib, DEV_DIS|DEV_DEBUG\r
397 },\r
398 {\r
399 "MTF", mtf_unit, mtf_reg, mt_mod,\r
400 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
401 NULL, NULL, &mt_reset,\r
402 NULL, &mt_attach, &sim_tape_detach,\r
403 &mt_dib, DEV_DIS|DEV_DEBUG\r
404 },\r
405 {\r
406 "MTG", mtg_unit, mtg_reg, mt_mod,\r
407 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
408 NULL, NULL, &mt_reset,\r
409 NULL, &mt_attach, &sim_tape_detach,\r
410 &mt_dib, DEV_DIS|DEV_DEBUG\r
411 },\r
412 {\r
413 "MTH", mth_unit, mth_reg, mt_mod,\r
414 MT_NUMDR + 1, 10, 31, 1, 8, 8,\r
415 NULL, NULL, &mt_reset,\r
416 NULL, &mt_attach, &sim_tape_detach,\r
417 &mt_dib, DEV_DIS|DEV_DEBUG\r
418 }\r
419 };\r
420\r
421/* Select controller\r
422\r
423 Inputs:\r
424 ch = channel\r
425 cmd = select command\r
426 unit = unit\r
427 Outputs:\r
428 status = SCPE_OK if ok\r
429 STOP_STALL if busy\r
430 error code if error\r
431*/\r
432\r
433static const int mt_must_att[CHSL_NUM] = {\r
434 0, 1, 1, 0, 1, 1, 0, 0,\r
435 1, 1, 1, 1, 1, 1, 0, 0\r
436 };\r
437\r
438static const int mt_will_wrt[CHSL_NUM] = {\r
439 0, 0, 1, 0, 0, 1, 0, 0,\r
440 1, 1, 0, 0, 0, 0, 0, 0\r
441 };\r
442\r
443t_stat mt_chsel (uint32 ch, uint32 cmd, uint32 unit)\r
444{\r
445UNIT *uptr;\r
446uint32 u = unit & 017;\r
447\r
448if ((ch >= NUM_CHAN) || (cmd == 0) || (cmd >= CHSL_NUM))\r
449 return SCPE_IERR; /* invalid arg? */\r
450if (mt_dev[ch].flags & DEV_DIS) return STOP_NXDEV; /* disabled? */\r
451if ((u == 0) || (u > MT_NUMDR)) return STOP_NXDEV; /* valid unit? */\r
452uptr = mt_dev[ch].units + u; /* get unit ptr */\r
453if (uptr->flags & UNIT_DIS) return STOP_NXDEV; /* disabled? */\r
454if (mt_unit[ch] || sim_is_active (uptr)) /* ctrl or unit busy? */\r
455 return ERR_STALL; /* stall */\r
456if (QCHRONO (ch, u)) { /* Chronolog clock? */\r
457 if (cmd != CHSL_RDS) return STOP_ILLIOP; /* only reads */\r
458 sim_activate (uptr, mt_tword); /* responds quickly */\r
459 }\r
460else { /* real tape */\r
461 if (!(uptr->flags & UNIT_ATT) && mt_must_att[cmd]) /* unit unatt? */\r
462 return SCPE_UNATT;\r
463 if (sim_tape_wrp (uptr) && mt_will_wrt[cmd]) /* unit wrp && write? */\r
464 return STOP_WRP;\r
465 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
466 ">>%s%d %s, pos = %d\n", mt_dev[ch].name, u, sel_name[cmd], uptr->pos);\r
467\r
468 switch (cmd) { /* case on cmd */\r
469\r
470 case CHSL_RDS:\r
471 case CHSL_WRS:\r
472 case CHSL_BSR:\r
473 case CHSL_BSF: /* rd, wr, backspace */\r
474 sim_activate (uptr, mt_tstart); /* schedule op */\r
475 break;\r
476\r
477 case CHSL_WEF: /* write eof? */\r
478 sim_activate (uptr, mt_twef); /* schedule op */\r
479 break;\r
480\r
481 case CHSL_RUN:\r
482 sim_activate (uptr, mt_tshort); /* schedule quick event */\r
483 break;\r
484 case CHSL_REW:\r
485 case CHSL_SDN: /* rew, rew/unl, set det */\r
486 sim_activate (uptr, mt_tshort); /* schedule quick event */\r
487 break;\r
488\r
489 default:\r
490 return SCPE_IERR;\r
491 } /* end switch */\r
492 } /* end else */\r
493\r
494uptr->UST = cmd; /* set cmd */\r
495mt_unit[ch] = unit & 0777; /* save unit */\r
496return SCPE_OK;\r
497}\r
498\r
499/* Channel write routine */\r
500\r
501t_stat mt_chwr (uint32 ch, t_uint64 val, uint32 eorfl)\r
502{\r
503int32 k, u;\r
504uint8 by, *xb;\r
505UNIT *uptr;\r
506\r
507if (ch >= NUM_CHAN) return SCPE_IERR; /* invalid chan? */\r
508xb = mtxb[ch]; /* get xfer buf */\r
509u = mt_unit[ch] & 017;\r
510if ((xb == NULL) || (u > MT_NUMDR)) return SCPE_IERR; /* invalid args? */\r
511uptr = mt_dev[ch].units + u; /* get unit */\r
512mt_chob[ch] = val & DMASK; /* save word from chan */\r
513mt_chob_v[ch] = 1; /* set valid */\r
514\r
515if (uptr->UST == (CHSL_WRS|CHSL_2ND)) { /* data write? */\r
516 for (k = 30; /* proc 6 bytes */\r
517 (k >= 0) && (mt_bptr[ch] < MT_MAXFR);\r
518 k = k - 6) {\r
519 by = (uint8) ((val >> k) & 077); /* get byte */\r
520 if ((mt_unit[ch] & 020) == 0) { /* BCD? */\r
521 if (by == 0) by = BCD_ZERO; /* cvt bin 0 */\r
522 else if (by & 020) by = by ^ 040; /* invert zones */\r
523 if (!odd_par[by]) by = by | 0100; /* even parity */\r
524 }\r
525 else if (odd_par[by]) by = by | 0100; /* bin, odd par */\r
526 xb[mt_bptr[ch]++] = by; /* put in buffer */\r
527 }\r
528 if (eorfl) return mt_rec_end (uptr); /* EOR? write rec */\r
529 return SCPE_OK;\r
530 }\r
531return SCPE_IERR;\r
532}\r
533\r
534/* Unit timeout */\r
535\r
536t_stat mt_svc (UNIT *uptr)\r
537{\r
538uint32 i, u, ch = uptr->UCH; /* get channel number */\r
539uint8 by, *xb = mtxb[ch]; /* get xfer buffer */\r
540t_uint64 dat;\r
541t_mtrlnt bc;\r
542t_stat r;\r
543\r
544if (xb == NULL) return SCPE_IERR; /* valid buffer? */\r
545u = uptr - mt_dev[ch].units;\r
546switch (uptr->UST) { /* case on state */\r
547\r
548 case CHSL_RDS: /* read start */\r
549 if (QCHRONO (ch, mt_unit[ch] & 017)) /* Chronolog clock? */\r
550 bc = chrono_rd (xb, MT_MAXFR); /* read clock */\r
551 else { /* real tape */\r
552 r = sim_tape_rdrecf (uptr, xb, &bc, MT_MAXFR); /* read record */\r
553 if (r = mt_map_err (uptr, r)) return r; /* map status */\r
554 if (mt_unit[ch] == 0) return SCPE_OK; /* disconnected? */\r
555 } /* end else Chrono */\r
556 if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */\r
557 mt_unit[ch] = 0; /* clr ctrl busy */\r
558 return SCPE_OK;\r
559 }\r
560 for (i = bc; i < (bc + 6); i++) xb[i] = 0; /* extra 0's */\r
561 mt_bptr[ch] = 0; /* set ptr, lnt */\r
562 mt_blnt[ch] = bc;\r
563 uptr->UST = CHSL_RDS|CHSL_2ND; /* next state */\r
564 sim_activate (uptr, mt_tword);\r
565 break;\r
566\r
567 case CHSL_RDS|CHSL_2ND: /* read word */\r
568 for (i = 0, dat = 0; i < 6; i++) { /* proc 6 bytes */\r
569 by = xb[mt_bptr[ch]++] & 077; /* get next byte */\r
570 if ((mt_unit[ch] & 020) == 0) { /* BCD? */\r
571 if (by == BCD_ZERO) by = 0; /* cvt BCD 0 */\r
572 else if (by & 020) by = by ^ 040; /* invert zones */\r
573 }\r
574 dat = (dat << 6) | ((t_uint64) by);\r
575 }\r
576 if (mt_bptr[ch] >= mt_blnt[ch]) { /* end of record? */\r
577 ch6_req_rd (ch, mt_unit[ch], dat, CH6DF_EOR);\r
578 uptr->UST = CHSL_RDS|CHSL_3RD; /* next state */\r
579 sim_activate (uptr, mt_tstop); /* long timing */\r
580 }\r
581 else {\r
582 ch6_req_rd (ch, mt_unit[ch], dat, 0); /* send to channel */\r
583 sim_activate (uptr, mt_tword); /* next word */\r
584 }\r
585 break;\r
586\r
587 case CHSL_RDS|CHSL_3RD: /* end record */\r
588 if (ch6_qconn (ch, mt_unit[ch])) { /* ch still conn? */\r
589 uptr->UST = CHSL_RDS; /* initial state */\r
590 sim_activate (uptr, mt_tshort); /* sched next record */\r
591 }\r
592 else mt_unit[ch] = 0; /* clr ctrl busy */\r
593 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
594 ">>%s%d RDS complete, pos = %d, %s\n",\r
595 mt_dev[ch].name, u, uptr->pos, mt_unit[ch]? "continuing": "disconnecting");\r
596 return SCPE_OK;\r
597\r
598 case CHSL_WRS: /* write start */\r
599 if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */\r
600 mt_unit[ch] = 0; /* clr ctrl busy */\r
601 return SCPE_OK; /* (writes blank tape) */\r
602 }\r
603 mt_bptr[ch] = 0; /* init buffer */\r
604 uptr->UST = CHSL_WRS|CHSL_2ND; /* next state */\r
605 ch6_req_wr (ch, mt_unit[ch]); /* request channel */\r
606 mt_chob[ch] = 0; /* clr, inval buffer */\r
607 mt_chob_v[ch] = 0;\r
608 sim_activate (uptr, mt_tword); /* wait for word */\r
609 break;\r
610\r
611 case CHSL_WRS|CHSL_2ND: /* write word */\r
612 if (!ch6_qconn (ch, mt_unit[ch])) /* disconnected? */\r
613 return mt_rec_end (uptr); /* write record */\r
614 if (mt_chob_v[ch]) mt_chob_v[ch] = 0; /* valid? clear */\r
615 else ind_ioc = 1; /* no, io check */\r
616 ch6_req_wr (ch, mt_unit[ch]); /* request channel */\r
617 sim_activate (uptr, mt_tword); /* next word */\r
618 break;\r
619\r
620 case CHSL_WRS|CHSL_3RD: /* write stop */\r
621 if (ch6_qconn (ch, mt_unit[ch])) { /* chan active? */\r
622 uptr->UST = CHSL_WRS; /* initial state */\r
623 sim_activate (uptr, mt_tshort); /* sched next record */\r
624 }\r
625 else mt_unit[ch] = 0; /* clr ctrl busy */\r
626 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
627 ">>%s%d WRS complete, pos = %d, %s\n",\r
628 mt_dev[ch].name, u, uptr->pos, mt_unit[ch]? "continuing": "disconnecting");\r
629 return SCPE_OK;\r
630\r
631 case CHSL_BSR: /* backspace rec */\r
632 r = sim_tape_sprecr (uptr, &bc); /* space backwards */\r
633 mt_unit[ch] = 0; /* clr ctrl busy */\r
634 ch6_end_nds (ch); /* disconnect */\r
635 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
636 ">>%s%d BSR complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);\r
637 if (r == MTSE_TMK) return SCPE_OK; /* allow tape mark */\r
638 return mt_map_err (uptr, r);\r
639\r
640 case CHSL_BSF: /* backspace file */\r
641 while ((r = sim_tape_sprecr (uptr, &bc)) == MTSE_OK) ;\r
642 mt_unit[ch] = 0; /* clr ctrl busy */\r
643 ch6_end_nds (ch); /* disconnect */\r
644 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
645 ">>%s%d BSF complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);\r
646 if (r == MTSE_TMK) return SCPE_OK; /* allow tape mark */\r
647 return mt_map_err (uptr, r); /* map others */\r
648\r
649 case CHSL_WEF: /* write eof */\r
650 r = sim_tape_wrtmk (uptr); /* write tape mark */\r
651 mt_unit[ch] = 0; /* clr ctrl busy */\r
652 ch6_end_nds (ch); /* disconnect */\r
653 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
654 ">>%s%d WEF complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);\r
655 return mt_map_err (uptr, r);\r
656\r
657 case CHSL_REW: case CHSL_RUN: /* rewind, unload */\r
658 uptr->UST = uptr->UST | CHSL_2ND; /* set 2nd state */\r
659 sim_activate (uptr, mt_tstart); /* reactivate */\r
660 mt_unit[ch] = 0; /* clr ctrl busy */\r
661 ch6_end_nds (ch); /* disconnect */\r
662 return SCPE_OK;\r
663\r
664 case CHSL_REW | CHSL_2ND:\r
665 sim_tape_rewind (uptr);\r
666 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
667 ">>%s%d REW complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);\r
668 return SCPE_OK;\r
669\r
670 case CHSL_RUN | CHSL_2ND:\r
671 sim_tape_detach (uptr);\r
672 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
673 ">>%s%d RUN complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);\r
674 return SCPE_OK;\r
675\r
676 case CHSL_SDN:\r
677 if (mt_unit[ch] & 020) /* set density flag */\r
678 uptr->flags = uptr-> flags & ~MTUF_LDN;\r
679 else uptr->flags = uptr->flags | MTUF_LDN;\r
680 mt_unit[ch] = 0; /* clr ctrl busy */\r
681 ch6_end_nds (ch); /* disconnect */\r
682 if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
683 ">>%s%d SDN complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);\r
684 return SCPE_OK;\r
685\r
686 default:\r
687 return SCPE_IERR;\r
688 }\r
689\r
690return SCPE_OK;\r
691}\r
692\r
693/* End record routine */\r
694\r
695t_stat mt_rec_end (UNIT *uptr)\r
696{\r
697uint32 ch = uptr->UCH;\r
698uint8 *xb = mtxb[ch];\r
699t_stat r;\r
700\r
701if (mt_bptr[ch]) { /* any data? */\r
702 if (xb == NULL) return SCPE_IERR;\r
703 r = sim_tape_wrrecf (uptr, xb, mt_bptr[ch]); /* write record */\r
704 if (r = mt_map_err (uptr, r)) return r; /* map error */\r
705 }\r
706uptr->UST = CHSL_WRS|CHSL_3RD; /* next state */\r
707sim_cancel (uptr); /* cancel current */\r
708sim_activate (uptr, mt_tstop); /* long timing */\r
709return SCPE_OK;\r
710}\r
711\r
712/* Map tape error status */\r
713\r
714t_stat mt_map_err (UNIT *uptr, t_stat st)\r
715{\r
716uint32 ch = uptr->UCH;\r
717uint32 u = mt_unit[ch];\r
718uint32 up = uptr - mt_dev[ch].units;\r
719\r
720if ((st != MTSE_OK) && DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,\r
721 ">>%s%d status = %s, pos = %d\n", mt_dev[ch].name, up, tape_stat[st], uptr->pos);\r
722\r
723switch (st) {\r
724\r
725 case MTSE_FMT: /* illegal fmt */\r
726 case MTSE_UNATT: /* not attached */\r
727 ch6_err_disc (ch, u, CHF_TRC);\r
728 mt_unit[ch] = 0; /* disconnect */\r
729 return SCPE_IERR;\r
730\r
731 case MTSE_IOERR: /* IO error */\r
732 ch6_err_disc (ch, u, CHF_TRC);\r
733 mt_unit[ch] = 0; /* disconnect */\r
734 return SCPE_IOERR;\r
735\r
736 case MTSE_INVRL: /* invalid rec lnt */\r
737 ch6_err_disc (ch, u, CHF_TRC);\r
738 mt_unit[ch] = 0; /* disconnect */\r
739 return SCPE_MTRLNT;\r
740\r
741 case MTSE_WRP: /* write protect */\r
742 ch6_err_disc (ch, u, 0);\r
743 mt_unit[ch] = 0; /* disconnect */\r
744 return STOP_WRP;\r
745\r
746 case MTSE_EOM: /* end of medium */\r
747 case MTSE_TMK: /* tape mark */\r
748 ch6_err_disc (ch, u, CHF_EOF);\r
749 mt_unit[ch] = 0; /* disconnect */\r
750 break;\r
751\r
752 case MTSE_RECE: /* record in error */\r
753 ch6_set_flags (ch, u, CHF_TRC);\r
754 break;\r
755\r
756 case MTSE_BOT: /* reverse into BOT */\r
757 ch6_set_flags (ch, u, CHF_BOT);\r
758 break;\r
759\r
760 case MTSE_OK: /* no error */\r
761 break;\r
762 }\r
763\r
764return SCPE_OK;\r
765}\r
766\r
767/* Magtape reset */\r
768\r
769t_stat mt_reset (DEVICE *dptr)\r
770{\r
771uint32 ch = dptr - &mt_dev[0];\r
772uint32 j;\r
773REG *rptr;\r
774UNIT *uptr;\r
775\r
776if (mtxb[ch] == NULL) mtxb[ch] = (uint8 *) calloc (MT_MAXFR + 6, sizeof (uint8));\r
777if (mtxb[ch] == NULL) return SCPE_MEM; /* allocate buffer */\r
778rptr = find_reg ("BUF", NULL, dptr); /* update reg ptr */\r
779if (rptr == NULL) return SCPE_IERR;\r
780rptr->loc = (void *) mtxb[ch];\r
781mt_unit[ch] = 0; /* clear busy */\r
782mt_bptr[ch] = 0; /* clear buf ptrs */\r
783mt_blnt[ch] = 0;\r
784mt_chob[ch] = 0;\r
785mt_chob_v[ch] = 0;\r
786for (j = 1; j <= MT_NUMDR; j++) { /* for all units */\r
787 uptr = dptr->units + j;\r
788 uptr->UST = 0; /* clear state */\r
789 uptr->UCH = ch;\r
790 sim_cancel (uptr); /* stop activity */\r
791 } /* end for */\r
792return SCPE_OK; /* done */\r
793}\r
794\r
795/* Magtape attach */\r
796\r
797t_stat mt_attach (UNIT *uptr, char *cptr)\r
798{\r
799uptr->flags = uptr->flags & ~MTUF_LDN; /* start as hi den */\r
800return sim_tape_attach (uptr, cptr);\r
801}\r
802\r
803/* Magtape boot */\r
804\r
805#define BOOT_START 01000\r
806\r
807static const t_uint64 boot_rom[5] = {\r
808 0076200000000 + U_MTBIN - 1, /* RDS MT_binary */\r
809 0054000000000 + BOOT_START + 4, /* RCHA *+3 */\r
810 0054400000000, /* LCHA 0 */\r
811 0002100000001, /* TTR 1 */\r
812 0500003000000, /* IOCT 0,,3 */\r
813 };\r
814\r
815t_stat mt_boot (int32 unitno, DEVICE *dptr)\r
816{\r
817uint32 i, chan;\r
818extern t_uint64 *M;\r
819\r
820chan = dptr - &mt_dev[0] + 1;\r
821WriteP (BOOT_START, boot_rom[0] + unitno + (chan << 9));\r
822for (i = 1; i < 5; i++)\r
823 WriteP (BOOT_START + i, boot_rom[i]);\r
824PC = BOOT_START;\r
825return SCPE_OK;\r
826}\r